我需要从PDF文件中读取字符串,并将其替换为Unicode text.If,它是ASCII字符,一切都很好。但与Unicode字符,它显示问号/垃圾text.No问题与字体文件(Ttf)我能够写一个unicode文本到pdf文件与一个不同的类(PDFContentStream)。对于这个类,没有替换文本的选项,但我们可以添加新文本。
示例unicode文本
Bɐɑɒ
问题(地址列)
https://drive.google.com/file/d/1DbsApTCSfTwwK3txsDGW8sXtDG_u-VJv/view?usp=sharing
我正在使用PDFBox。请帮帮我……
检查我正在使用的代码.....
enter image description herepublic static PDDocument _ReplaceText(PDDocument document, String searchString, String replacement)
throws IOException {
if (StringUtils.isEmpty(searchString) || StringUtils.isEmpty(replacement)) {
return document;
}
for (PDPage page : document.getPages()) {
PDResources resources = new PDResources();
PDFont font = PDType0Font.load(document, new File("arial-unicode-ms.ttf"));
//PDFont font2 = PDType0Font.load(document, new File("avenir-next-regular.ttf"));
resources.add(font);
//resources.add(font2);
//resources.add(PDType1Font.TIMES_ROMAN);
page.setResources(resources);
PDFStreamParser parser = new PDFStreamParser(page);
parser.parse();
List tokens = parser.getTokens();
for (int j = 0; j < tokens.size(); j++) {
Object next = tokens.get(j);
if (next instanceof Operator) {
Operator op = (Operator) next;
String pstring = "";
int prej = 0;
// Tj and TJ are the two operators that display strings in a PDF
if (op.getName().equals("Tj")) {
// Tj takes one operator and that is the string to display so lets update that
// operator
COSString previous = (COSString) tokens.get(j - 1);
String string = previous.getString();
string = string.replaceFirst(searchString, replacement);
previous.setValue(string.getBytes());
} else if (op.getName().equals("TJ")) {
COSArray previous = (COSArray) tokens.get(j - 1);
for (int k = 0; k < previous.size(); k++) {
Object arrElement = previous.getObject(k);
if (arrElement instanceof COSString) {
COSString cosString = (COSString) arrElement;
String string = cosString.getString();
if (j == prej) {
pstring += string;
} else {
prej = j;
pstring = string;
}
}
}
if (searchString.equals(pstring.trim())) {
COSString cosString2 = (COSString) previous.getObject(0);
cosString2.setValue(replacement.getBytes());
int total = previous.size() - 1;
for (int k = total; k > 0; k--) {
previous.remove(k);
}
}
}
}
}
// now that the tokens are updated we will replace the page content stream.
PDStream updatedStream = new PDStream(document);
OutputStream out = updatedStream.createOutputStream(COSName.FLATE_DECODE);
ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
tokenWriter.writeTokens(tokens);
out.close();
page.setContents(updatedStream);
}
return document;
}
发布于 2018-05-28 17:19:42
你的代码完全破坏了PDF,cf。Adobe印前检查输出:
原因很明显,您的代码
PDResources resources = new PDResources();
PDFont font = PDType0Font.load(document, new File("arial-unicode-ms.ttf"));
resources.add(font);
page.setResources(resources);
删除先前存在的页面资源,替换后的页面只包含一种字体,您可以让PDFBox任意选择该字体的名称。
不能删除现有资源,因为它们已在文档中使用。
检查您的PDF页面的内容,您会发现原来使用的字体T1_和T1_1的编码要么是单字节编码,要么是混合的单字节/多字节编码;较低的单字节值似乎是类似ASCII码编码的。
我假设编码是WinAnsiEncoding或其子集。作为推论,你的任务
从
文件中读取字符串并将其替换为Unicode文本
不能作为简单的替代实现,至少不能考虑到任意的Unicode代码点。
相反,您可以实现的是:
PDFContentStream
在确定的位置添加替换内容;为此,请将新字体添加到现有资源中。但是请注意,PDF不是这样设计的。模板PDF可以用作新内容的背景,但尝试替换其中的内容通常是导致麻烦的糟糕设计。如果您需要标记模板中的位置,请使用可以在填写过程中轻松删除的注释。或者首先使用原生AcroForm表单技术。
https://stackoverflow.com/questions/50546388
复制相似问题