当前位置: 首页 > 知识库问答 >
问题:

"Tj"到java字符串编码问题(PDFBox)

尉迟远
2023-03-14

我尝试使用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);

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

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

正如您所看到的,“(有些字符串)Tj”行变成了“(”...
在eclipse的调试模式下,当程序到达该行时,“line”变量包含以下值:

"(

(与其他以秒结尾的字符串不同,“(”)后面没有任何内容)
如果扩展字符串值,则会得到以下字符数组

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

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

我已经试过了

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

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

谢谢你的帮助。

共有1个答案

卜鹏
2023-03-14

有人能给我解释一下问题是什么吗

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

这是错误的。

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

引用规范:

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

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

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

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

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

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

如何解决

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

因此,您可能想看看

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

根据OP的后续评论:

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

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

PDFTextStripper扩展了类PDFTextStreamEngine,该类又扩展了PDFStreamEngine

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

PDFTextStreamEngine是PDFStreamEngine的子类,用于通过TextPosition对文本进行高级处理。

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

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

 类似资料:
  • 我们都知道计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),0 - 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母 A 的编码是 65,小写字母 z 的编码是 122。 如果要表示中

  • 我遇到了一个关于编码蝙蝠的问题,问题是: 给定一个字符串,返回一个由原始字符串的最后2个字符的3个副本组成的新字符串。字符串长度至少为2。我解决了这个问题,解决方案(下图)比我的好,但是,解决方案代码有一个问题,当字符串长度小于2时,假设长度只有1。str索引将是-1。代码还能工作吗?为什么网站说解决方案是正确的?

  • 所以我有这个文件(http://mountainmarathon.ch/components/com_chronoconnectivity6/chronoconnectivity/uploads/20190814194827_classifica-cat-standard-3.csv)哪个“应该”用utf-8编码。当我试图通过fgetcsv或file_get_内容读取内容时,我得到了那些黑色钻石,

  • 问题内容: 我目前正在使用ReactJS和webpack构建一个网站。 我的文本编辑器设置为编码,并且使用带重音或特殊字符的字符,例如。 在我的html页面中,我相信我使用的配置正确: 但是特殊字符的渲染方式不正确: 例如,而不是。 我尝试设置,但没有任何改变。 我觉得webpack正在使用编码构建,这使我的角色停滞不前。我该如何解决这个问题? 问题答案: 我没有找到一种使Webpack读取UTF

  • 问题内容: 我遇到了这行遗留代码,我试图找出这些遗留代码: 据我了解,它是使用相同的charSet进行编码和解码。 这与以下内容有何不同? 在任何情况下,两条生产线的输出将不同? ps:只是要澄清一下,是的,我知道Joel Spolsky撰写的关于编码 的出色文章! 问题答案: 这可能是很复杂的方式 这缩短了String,而所使用的基础char []则更长。 但是,更具体地说,将检查每个字符是否都

  • 对于Java/general中有关此概念的任何好的参考资料,我们将不胜感激。