“(someString) Tj”到 java 字符串编码问题 (PDFBox)

"(someString) Tj" to java String encoding probleme (PDFBox)

我尝试使用 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”行时:这里是我的代码的输出示例 return:

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

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

"(

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

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

一些空例 return 一个 "void" 值(在 eclipse 中引发 "Generated value (void) is not compatible with declared type (char)" 错误),其他包含一些无法理解的字符。我认为问题出在错误的字符编码上,但我找不到解决方案。

我已经尝试过

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

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

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

感谢您的帮助。

问题

Can someone explain to me what the problem is

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

这是错误的。

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

引用规范:

A string operand of a text-showing operator shall be interpreted as a sequence of character codes identifying the glyphs to be painted.

With a simple font, each byte of the string shall be treated as a separate character code. The character code shall then be looked up in the font’s encoding to select the glyph, as described in 9.6.6, "Character Encoding".

With a composite font (PDF 1.2), multiple-byte codes may be used to select glyphs. In this instance, one or more consecutive bytes of the string shall be treated as a single character code. The code lengths and the mappings from codes to glyphs are defined in a data structure called a CMap, described in 9.7, "Composite Fonts".

(section 9.4.3 Text-Showing Operators of ISO 32000-1)

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

因此,要正确解析内容流,您必须将它们视为二进制数据,并根据 当前字体 在内容流。

一个解决方案

how to solve it

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

因此,您可能想看看

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

来自 OP 的后续评论:

I choose this approach to extract the PDF's content because what I want to extract isn't some text but vector-made schemas. The text I try to extract in this particular problem is the variables that are link to specifics parts of the schema. That's why I can't really use 'PDFTextStripper', since I need global information on the vectors that are around the text I extract. But maybe my approach is wrong from the beginning ...

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

PDFTextStripper 扩展了 class PDFTextStreamEngine,后者又扩展了 PDFStreamEngine.

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

PDFTextStreamEnginePDFStreamEngine subclass,用于通过 TextPosition.

对文本进行高级处理

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

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