java - 如何在 pdfbox 2.0.0 上的 truetype0font 中添加 unicode?

标签 java unicode pdfbox glyph

我一直在 Java 项目中使用 PDFBOX 2.0.0 版将 pdf 转换为文本。

我的几个 pdf 缺少 ToUnicode 方法,所以当我导出它们时,它们会以乱码形式出现。
2016-09-14 10:44:55 WARN org.apache.pdfbox.pdmodel.font.PDSimpleFont(1):322 - No Unicode mapping for 694 (30) in font MPBAAA+F1
在上面的 WARN 中,不是真实字符,而是一个乱码 unicode (30)。

我能够通过编辑 additional.txt 来克服它。 pdfbox 中的文件,因为从反复试验中我了解到字符的代码(在这种情况下为 694)代表某个希伯来字母(צ)。

这是我在文件中编辑的内容的简短示例:

-694;05E6 #HexaDecimal value for the letter צ
-695;05E7
-696;05E8

后来我在不同的 pdf 上遇到了几乎相同的警告,但我没有得到任何字符,而不是乱码。
可以在此处查看此问题的更详细说明 - pdf reading via pdfbox in java
2016-09-14 11:07:10 WARN org.apache.pdfbox.pdmodel.font.PDType0Font(1):431 - No Unicode mapping for CID+694 (694) in font ABCDEE+Tahoma,Bold
如您所见,警告来自不同的类( PDType0Font )而不是第一个警告( PDSimpleFont ),但是它们的代号 (694) 是相同的,并且它们都在谈论相同的内容特点。

除了 additional.txt 之外,还有其他我应该编辑的文件吗?将 694 代码(希伯来字母 צ)指向正确的 unicode?

谢谢
main root

drill down on the first type0 font

最佳答案

下面是一些在字体中添加 ToUnicode CMap 流的代码。显然我不能用你的文件来做,所以我用了我的一个测试文件,可以找到 here .我不得不单独处理每个条目,并没有完成所有工作。然而,结果足以提取绿色打印中的第一个单词(“Bedingungen”)。

该场景有点适合您:

  • 身份-H条目
  • 没有 ToUnicode 条目
  • 具体字体名称
    try (PDDocument doc = PDDocument.load(f))
    {
        for (int p = 0; p < doc.getNumberOfPages(); ++p)
        {
            PDPage page = doc.getPage(p);
            PDResources res = page.getResources();
            for (COSName fontName : res.getFontNames())
            {
                PDFont font = res.getFont(fontName);
                COSBase encoding = font.getCOSObject().getDictionaryObject(COSName.ENCODING);
                if (!COSName.IDENTITY_H.equals(encoding))
                {
                    continue;
                }
                // get real name
                String fname = font.getName();
                int plus = fname.indexOf('+');
                if (plus != -1)
                {
                    fname = fname.substring(plus + 1);
                }
                if (font.getCOSObject().containsKey(COSName.TO_UNICODE))
                {
                    continue;
                }
                System.out.println("File '" + f.getName() + "', page " + (p + 1) + ", " + fontName.getName() + ", " + font.getName());
                if (!fname.startsWith("Calibri-Bold"))
                {
                    continue;
                }
                COSStream toUnicodeStream = new COSStream();
                try (PrintWriter pw = new PrintWriter(toUnicodeStream.createOutputStream(COSName.FLATE_DECODE)))
                {
                    // "9.10 Extraction of Text Content" in the PDF 32000 specification
                    pw.println ("/CIDInit /ProcSet findresource begin\n" +
                            "12 dict begin\n" +
                            "begincmap\n" +
                            "/CIDSystemInfo\n" +
                            "<< /Registry (Adobe)\n" +
                            "/Ordering (UCS) /Supplement 0 >> def\n" +
                            "/CMapName /Adobe-Identity-UCS def\n" +
                            "/CMapType 2 def\n" +
                            "1 begincodespacerange\n" +
                            "<0000> <FFFF>\n" +
                            "endcodespacerange\n" +
                            "10 beginbfchar\n" + // number is count of entries
                            "<0001><0020>\n" + // space
                            "<0002><0041>\n" + // A
                            "<0003><0042>\n" + // B
                            "<0004><0044>\n" + // D
                            "<0013><0065>\n" + // e
                            "<0012><0064>\n" + // d
                            "<0017><0069>\n" + // i
                            "<001B><006E>\n" + // n
                            "<0015><0067>\n" + // g
                            "<0020><0075>\n" + // u
                            "endbfchar\n" +
                            "endcmap CMapName currentdict /CMap defineresource pop end end");
                }
                font.getCOSObject().setItem(COSName.TO_UNICODE, toUnicodeStream);
            }
        }
        doc.save("huhu.pdf");
    }
    

  • 顺便说一句,未发布的 2.1 版本的 PDFDebugger 有一些改进的功能来显示字体,你可以得到它 here :

    您可以使用它来验证您的 ToUnicode CMap 是否有意义。以下是我所做的更改:
    enter image description here

    关于java - 如何在 pdfbox 2.0.0 上的 truetype0font 中添加 unicode?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39485920/

    相关文章:

    java - 如何在 JLabel 或 java 中显示 🔴

    javascript - 取消转义 JavaScript 中的转义字符串

    c++ - cocos2d-x C++ 字符串unicode转换

    java - 使用 PDFBox 解析 PDF 文件(尤其是带有表格的文件)

    pdfbox - 登录 Apache PDFBox 2.0 时出现 "You did not close a PDF Document"

    java - HtmlUnit 从 Div 中抓取 Xpath

    java - 在jdk1.7中无法编译运行HelloWorld

    java - 如何替换字符串中的多个字符?

    java - 如何在代码中的任意位置访问 JAAS 角色?

    java - 使用 pdfbox 计算 pdf 中的图像数量