首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用PDFbox在pdf文件中用unicode文本替换字符串?

用PDFbox在pdf文件中用unicode文本替换字符串?
EN

Stack Overflow用户
提问于 2018-05-27 03:35:19
回答 1查看 877关注 0票数 0

我需要从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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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代码点。

相反,您可以实现的是:

  • 首先通过一个定制的文本剥离器运行您的源PDF,它不是提取纯文本,而是搜索要替换的字符串并返回它们的位置。这里有许多问题和答案,向你展示了如何确定文本剥离器子类中字符串的坐标,最近的一个问题是this one.
  • Next remove那些原始字符串。在您的示例中,一种与上面的原始代码类似的方法(显然不会删除资源),用同样长的空格字符串替换字符串可能会起作用,即使它是一个脏的hack.
  • Finally在附加模式下使用PDFContentStream在确定的位置添加替换内容;为此,请将新字体添加到现有资源中。

但是请注意,PDF不是这样设计的。模板PDF可以用作新内容的背景,但尝试替换其中的内容通常是导致麻烦的糟糕设计。如果您需要标记模板中的位置,请使用可以在填写过程中轻松删除的注释。或者首先使用原生AcroForm表单技术。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50546388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档