我有使用文件文本类从PDF中提取文本的代码。直到上个星期当pdf中发生了一些变化。奇怪的是,一旦我将29个字符添加到字符的ord中,字符就会出现并更正。
示例响应调试打印:
/F1 7.31 Tf
0 0 0 rg
1 0 0 1 195.16 597.4 Tm
($PRXQW)Tj
ET
BT代码在pdf的流部分使用gzuncompress。$PRXQW是数量,并将29 each添加到每个字符的ord中,这给了我这个结果。但有时字符将不是这个确切的翻译,如什么应该是一个)在文本中似乎是两个字节的5C66。
只是想知道这个代码环类型的字符现在从PDF出来,如果有人见过这样的事情?
发布于 2015-08-14 07:52:32
Tj操作的字符串参数的编码完全取决于所使用的PDF字体(在当前情况下为F1):
文本显示操作符的字符串操作数应解释为标识要绘制的符号的字符代码序列。 对于简单的字体,字符串的每个字节都应被视为单独的字符代码。然后在字体的编码中查找字符代码,以选择字形,如9.6.6所述,“字符编码”。 使用组合字体(PDF 1.2),可以使用多字节代码来选择象形文字.在这种情况下,字符串的一个或多个连续字节将被视为单个字符代码。代码长度和从代码到象形文字的映射是在称为CMap的数据结构中定义的,在9.7中描述了“复合字体”。 (http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf中的9.4.3节“文本-显示操作符”)
OP的代码似乎假定了标准编码,如MacRomanEncoding或WinAnsiEncoding,,但这些只是特例。正如上面的引号所指出的,编码可能也是一些特殊的混合多字节编码。
后面一节中的PDF规范描述了如何正确提取文本:
符合标准的读取器可以按照给定的优先级使用这些方法将字符代码映射到Unicode值。特别是有标记的PDF文档至少应提供其中一种方法(见14.8.2.4.2,“以标记PDF表示的Unicode映射”):
如果这些方法无法生成Unicode值,则无法确定字符代码代表什么,在这种情况下,符合条件的读者可以选择他们选择的字符代码。
(http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf中的9.10.2节“将字符代码映射到Unicode值”)
因此:
只是想知道这个代码环类型的字符现在从PDF出来,如果有人见过这样的事情?
是的,在来自野外的PDF中,使用文本绘制操作符字符串参数与ASCII‘’ish完全不同的编码是相当普遍的。正如上面第二段引文中的最后一段所暗示的那样,在某些情况下根本不允许文本提取(没有OCR,也就是说),尽管还有其他地方可以查找到Unicode的映射。
发布于 2016-03-20 07:11:04
在最一般的情况下,您想要解码的神秘字符串是所选字体的/Encoding字段,在您的示例中是字体/F1。更有可能的是,编码方案是/Identity-H,它可以包含PDF字符串中的16位字符到UTF-16字符的任意映射。
下面是我正在编写的PDF解析器的一个示例。每个页面都包含一个资源字典,其中包含一个字体字典:
[&3|0] => Array [
[/Type] => |/Page|
[/Resources] => Array [
[/Font] => Array [
[/F1] => |&5|0|
[/F2] => |&7|0|
[/F3] => |&9|0|
[/F4] => |&14|0|
[/F5] => |&16|0|
]
]
[/Contents] => |&4|0|
]在我的例子中,/F3产生了不可用的文本,所以看看/F3:
[&9|0] => Array [
[/Type] => |/Font|
[/Subtype] => |/Type0|
[/BaseFont] => |/Arial|
[/Encoding] => |/Identity-H|
[/DescendantFonts] => |&10|0|
[/ToUnicode] => |&96|0|
]在这里您可以看到/Encoding类型是/Identity-H。/F3中使用的解码字符的字符解码映射存储在/ToUnicode引用的流中。以下是‘&96_
...
beginbfchar
<0003> <0020>
<000F> <002C>
<0015> <0032>
<001B> <0038>
<002C> <0049>
<003A> <0057>
endbfchar
...
beginbfrange
<0044> <0045> <0061>
<0047> <004C> <0064>
<004F> <0053> <006C>
<0055> <0059> <0072>
endbfrange
...
beginbfchar
<005C> <0079>
<00B1> <2013>
<00B6> <2019>
endbfchar
...pairs /endbfchar之间的16位对是单个字符的映射。例如,<0003> (0x0003)映射到<0020> (0x0020),这是空格字符。
16位三重奏在起始范围/结束范围之间是字符范围的映射。例如,从<0055> (第一个)到<0059> (最后)的字符映射到<0072>、<0073>、<0074>、<0075>和<0076> ( UTF16 &ASCII中从‘r’到'v‘)。
https://stackoverflow.com/questions/32000107
复制相似问题