【问题标题】:"(someString) Tj" to java String encoding probleme (PDFBox)“(someString)Tj”到java字符串编码问题(PDFBox)
【发布时间】:2016-03-14 13:35:23
【问题描述】:

我尝试使用 PDFBox 2.0.0 解析 PDF 的内容流。
这是处理它的代码的一部分:

InputStream is;
try {
    is = this.input.getDocumentCatalog().getPages().get(page).getContents();
} catch (IOException e) {
    e.printStackTrace();
    return;
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));

String line;
do {
    try {
        line = br.readLine();
    } catch (IOException e) {
        e.printStackTrace();
        try {
            br.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return;
    }
    if(line != null){
        System.out.println(line);
    }
}while(line != null);

问题是当我到达“(someString)Tj”行时:这里是我的代码返回的输出示例:

BT
/F2 7.0866 Tf
0 Tr
7.0866 TL
0.001 Tc
65 Tz
0 0 Td
(
ET

如您所见,“(someString) Tj”行变成了“(” ...
在eclipse的调试模式下,当程序到达这一行时,“line”变量包含以下值:

"(

(以 " 开头,'(' 后面没有任何内容,这与任何其他以第二个 " 结尾的字符串不同)。
如果我扩展 String 值,我会得到以下 char 数组:

[0] (   
[1] 
[2] %   
[3] 
[4] $   
[5] 
[6] 
[7] 
[8] 
[9] )
[10]T   
[11]j   

一些空案例返回一个“void”值(在 eclipse 中引发“生成的值(void)与声明的类型(char)不兼容”错误),其他包含一些无法理解的字符。我认为问题来自错误的字符编码,但我找不到解决方案。

我已经尝试过一些类似的东西

line = new String(br.readLine().getBytes("UTF-8"), "UTF-8");

差不多,但由于我不确定问题是什么,所以很难解决。

有人可以向我解释一下问题是什么以及最终如何解决它吗?

感谢您的帮助。

【问题讨论】:

    标签: java string pdf encoding pdfbox


    【解决方案1】:

    问题

    谁能解释一下问题出在哪里

    问题在于您试图将内容流视为由某种单一标准编码的纯文本数据组成。

    这是错误的。

    虽然确实以 ASCII 格式给出了运算符和数字参数,但显示运算符的文本的字符串参数的内容可能以完全不同于 ASCII 数据的方式编码(更不用说 UTF-8 编码的) )。

    引用规范:

    文本显示运算符的字符串操作数应被解释为标识要绘制的字形的字符代码序列。

    对于简单字体,字符串的每个字节都应被视为一个单独的字符代码。然后应在字体的编码中查找字符代码以选择字形,如 9.6.6 “字符编码”中所述。

    对于复合字体 (PDF 1.2),可以使用多字节代码来选择字形。在这种情况下,字符串的一个或多个连续字节应被视为单个字符代码。代码长度以及从代码到字形的映射在称为 CMap 的数据结构中定义,如 9.7 “复合字体”中所述。

    (第 9.4.3 节ISO 32000-1 的文本显示运算符

    如果使用标准编码,这些特定于字体的编码可能会让人想起 ASCII 或 Latin-1 或类似编码,但尤其是在部分嵌入字体的情况下,您经常会发现与已知编码没有任何关系的 ad-hoc 编码。

    因此,要正确解析内容流,您必须将它们视为二进制数据,并根据内容流中该位置的当前字体的编码来解释字符串操作数。

    解决方案

    如何解决

    在 PDFBox 中,有些类已经解释了内容流并尝试为绘制的文本找到 Unicode 字符串表示。

    因此,您可能想看看

    • PDFTextStripper 类,这是基本的 PDFBox 文本提取类;
    • 派生自PDFTextStripper 的类提供特殊的文本提取问题解决方案,例如用于从页面上的给定区域提取文本;
    • PDFTextStripper派生自,它提供了一个通用的内容流解析框架;和
    • PDFBox 示例类侧重于上述所有内容,说明了它们的用法。

    来自 OP 的后续评论:

    我选择这种方法来提取 PDF 的内容是因为我想要提取的不是一些文本,而是矢量制作的模式。我试图在这个特定问题中提取的文本是链接到模式的特定部分的变量。这就是我不能真正使用“PDFTextStripper”的原因,因为我需要关于我提取的文本周围的向量的全局信息。但也许我的方法从一开始就错了……

    要正确解析这些文本,您必须做一些类似于文本剥离器所做的事情,我建议不要重新发明轮子

    PDFTextStripper 扩展了 PDFTextStreamEngine 类,后者又扩展了 PDFStreamEngine

    PDFStreamEngine是一个处理PDF内容流并执行某些操作的类;它为想要处理流的客户端提供了一个回调接口。

    PDFTextStreamEnginePDFStreamEngine 子类,用于通过TextPosition 进行文本高级处理。

    您可能希望为您的任务扩展后两个类之一,并为矢量图形操作创建和注册回调。这些回调可以收集你需要的矢量图形操作。文本数据的并行回调提供链接到特定部分的变量

    使用这些类可能会带来一定程度的复杂性,您将不得不对它们进行一些研究,但是一旦您了解了它们的内部工作原理,它们很可能会成为您的基础需要。

    【讨论】:

    • 谢谢!但我选择这种方法来提取 PDF 的内容,因为我要提取的不是一些文本,而是矢量制作的模式。我试图在这个特定问题中提取的文本是链接到模式的特定部分的变量。这就是我不能真正使用“PDFTextStripper”的原因,因为我需要关于我提取的文本周围的向量的全局信息。但也许我的方法从一开始就错了……你怎么看?
    • 从本质上讲,您要么重新发明轮子(即正确的文本提取,实际上是一项壮举),要么切换到使用文本剥离器所依赖的框架,这需要一些工作。
    • 是的,重新发明轮子是我的热情 :) 谢谢!
    猜你喜欢
    • 2013-09-19
    • 2013-08-22
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多