我在同一个 PDF 页面中,在不同的 ObjectX 中有以下内容:
首先:
[(some text)] TJ ET Q
[(some other text)] TJ ET Q
到目前为止非常简单和基本...
第二个:
[( H T M L E x a m p l e)] TJ ET Q
[( S o m e s p e c i a l c h a r a c t e r s : < ¬ ¬ ¬ & ט ט © > \\ s l a s h \\ \\ d o u b l e - s l a s h \\ \\ \\ t r i p l e - s l a s h )] TJ ET Q
注意:在上面的文字中并不明显,但是:
'H T M L E x a m p l e' 实际上是 0H0T0M0L0[32]0E0x0a0m0p0l0e 其中每个 0 都是一个字面值 0 == ((char)0) 所以如果我忽略所有 0 值,这实际上会变成像上面的例子...
一些字节:
htmlexample == [0, 72, 0, 84, 0, 77, 0, 76, 0, 32, 0, 69, 0, 120, 0, 97, 0, 109, 0, 112, 0, 108, 0, 101]
<content> == [0, 32, 32, -84, 0, 32, 32, -84, 0, 32, 32, -84, 0, 32, 0, 38, 0, 32, 0, -24, 0, 32, 0, -24, 0, 32, 0, -87, 0, 32, 0]
但在下一行中,由于以下原因,我需要将每两个字节组合成一个字符:
< ¬ ¬ ¬...> 实际上是 <0[32][32]¬0[32][32]¬0[32][32]¬...> 其中 [32]¬ 的组合是€
我面临的问题不是我使用的转换本身: 新字符串(sb.toString().getBytes("UTF-8"),"UTF-16BE")
问题是要知道何时应用它以及何时保留 UTF-8。
== 更新 ==
用于有问题的对象的字体是:
#7 0# {
'Name' : "F4"
'BaseFont' : "AAAAAE+DejaVuSans-Bold"
'Subtype' : "Type0"
'ToUnicode' : #41 0# {
'Filter' : "FlateDecode"
'Length' : 1679.0f
} + Stream(5771 bytes)
'Encoding' : "Identity-H"
'DescendantFonts' : [#42 0# {
'FontDescriptor' : #43 0# {
'MaxWidth' : 2016.0f
'AvgWidth' : 573.0f
'FontBBox' : [-1069.0f, -415.0f, 1975.0f, 1174.0f]
'MissingWidth' : 600.0f
'FontName' : "AAAAAE+DejaVuSans-Bold"
'Type' : "FontDescriptor"
'CapHeight' : 729.0f
'StemV' : 60.0f
'Leading' : 0.0f
'FontFile2' : #34 0# {
'Filter' : "FlateDecode"
'Length1' : 83036.0f
'Length' : 34117.0f
} + Stream(83036 bytes)
'Ascent' : 928.0f
'Descent' : -236.0f
'XHeight' : 547.0f
'StemH' : 26.0f
'Flags' : 32.0f
'ItalicAngle' : 0.0f
}
'Subtype' : "CIDFontType2"
'W' : [32.0f, [348.0f, 456.0f, 521.0f, 838.0f, 696.0f, 1002.0f, 872.0f, 306.0f, 457.0f, 457.0f, 523.0f, 838.0f, 380.0f, 415.0f, 380.0f, 365.0f], 48.0f, 57.0f, 696.0f, 58.0f, 59.0f, 400.0f, 60.0f, 62.0f, 838.0f, 63.0f, [580.0f, 1000.0f, 774.0f, 762.0f, 734.0f, 830.0f, 683.0f, 683.0f, 821.0f, 837.0f, 372.0f, 372.0f, 775.0f, 637.0f, 995.0f, 837.0f, 850.0f, 733.0f, 850.0f, 770.0f, 720.0f, 682.0f, 812.0f, 774.0f, 1103.0f, 771.0f, 724.0f, 725.0f, 457.0f, 365.0f, 457.0f, 838.0f, 500.0f, 500.0f, 675.0f, 716.0f, 593.0f, 716.0f, 678.0f, 435.0f, 716.0f, 712.0f, 343.0f, 343.0f, 665.0f, 343.0f, 1042.0f, 712.0f, 687.0f, 716.0f, 716.0f, 493.0f, 595.0f, 478.0f, 712.0f, 652.0f, 924.0f, 645.0f, 652.0f, 582.0f, 712.0f, 365.0f, 712.0f, 838.0f], 160.0f, [348.0f, 456.0f, 696.0f, 696.0f, 636.0f, 696.0f, 365.0f, 500.0f, 500.0f, 1000.0f, 564.0f, 646.0f, 838.0f, 415.0f, 1000.0f, 500.0f, 500.0f, 838.0f, 438.0f, 438.0f, 500.0f, 736.0f, 636.0f, 380.0f, 500.0f, 438.0f, 564.0f, 646.0f], 188.0f, 190.0f, 1035.0f, 191.0f, 191.0f, 580.0f, 192.0f, 197.0f, 774.0f, 198.0f, [1085.0f, 734.0f], 200.0f, 203.0f, 683.0f, 204.0f, 207.0f, 372.0f, 208.0f, [838.0f, 837.0f], 210.0f, 214.0f, 850.0f, 215.0f, [838.0f, 850.0f], 217.0f, 220.0f, 812.0f, 221.0f, [724.0f, 738.0f, 719.0f], 224.0f, 229.0f, 675.0f, 230.0f, [1048.0f, 593.0f], 232.0f, 235.0f, 678.0f, 236.0f, 239.0f, 343.0f, 240.0f, [687.0f, 712.0f, 687.0f, 687.0f, 687.0f, 687.0f, 687.0f], 247.0f, [838.0f, 687.0f], 249.0f, 252.0f, 712.0f, 253.0f, [652.0f, 716.0f]]
'Type' : "Font"
'BaseFont' : "AAAAAE+DejaVuSans-Bold"
'CIDSystemInfo' : {
'Supplement' : 0.0f
'Ordering' : "Identity" + Stream(8 bytes)
'Registry' : "Adobe" + Stream(5 bytes)
}
'DW' : 600.0f
'CIDToGIDMap' : #44 0# {
'Filter' : "FlateDecode"
'Length' : 10200.0f
} + Stream(131072 bytes)
}]
'Type' : "Font"
}
没有指示字体的编码类型。
== 更新 ==
至于 ToUnicode 对象,在这些字体的情况下,它是不必要的,它应该是 Identity-H,但它是一个 X == X 映射,这里是一些从 FFFF 开始的示例:
<0000> <00ff> <0000>
<0100> <01ff> <0100>
<0200> <02ff> <0200>
<0300> <03ff> <0300>
<0400> <04ff> <0400>
<0500> <05ff> <0500>
<0600> <06ff> <0600>
<0700> <07ff> <0700>
<0800> <08ff> <0800>
<0900> <09ff> <0900>
<0a00> <0aff> <0a00>
<0b00> <0bff> <0b00>
<0c00> <0cff> <0c00>
<0d00> <0dff> <0d00>
<0e00> <0eff> <0e00>
<0f00> <0fff> <0f00>
<1000> <10ff> <1000>
<1100> <11ff> <1100>
....
....
....
<fc00> <fcff> <fc00>
<fd00> <fdff> <fd00>
<fe00> <feff> <fe00>
<ff00> <ffff> <ff00>
所以映射不在ToUnicode对象中,但其他渲染器仍然可以很好地渲染它!
有什么想法吗?
最佳答案
I use: new String(sb.toString().getBytes("UTF-8"),"UTF-16BE")
The problem is to know when to apply it and when to keep the UTF-8.
OP 可能在检查了一些示例 PDF 文件之后假设 PDF 内容流中的字符串是使用 UTF-8 或 UTF-16BE 编码的。
这个假设是错误的。
PDF 允许一些标准的单字节编码(MacRomanEncoding、MacExpertEncoding 和 WinAnsiEncoding),其中没有一个是 UTF-8(由于不同编码之间的关系,尤其是 ASCII、Latin1 和 UTF-8,在样本有限的情况下,它们可能会相互混淆)。此外,还允许使用许多预定义的多字节编码,其中一些确实与 UTF-16 相关..
但 PDF 也允许使用完全自定义的编码,包括单字节和多字节!
例如本次文字绘制操作
(ABCCD) Tj
对于使用这种编码的简单字体:
<<
/Type /Encoding
/Differences [ 65 /H /e /l /o ]
>>
显示单词 Hello!
虽然这可能看起来像一个人工构造的示例,但创建这样的自定义编码的过程(即通过将代码从某个起始值向上分配给字形,按照它们在页面或文档中首次出现的顺序) 经常使用。
此外,OP当前的解决方案
If your font object has a CMap, then you treat it as a UTF-16, otherwise not.
只适用于极少数文档,因为
a) 简单字体(使用单字节编码)也可以提供一个ToUnicode CMap 和 b) 复合字体 CMap 也不需要类似 UTF,而是可以使用混合多字节编码。
因此,无法深入分析使用的字体信息,cf。 PDF specification 的 9.5..9.9 ISO 32000-1。
PS 关于 OP 的一些评论:
this: new String(sb.toString().getBytes("UTF-8"),"UTF-16BE") was an example to the how the problem is solved not a solution! The solution is done while fetching the glyphs whether I treat the data as 16-bit or 8-bit
和
the ToUnicode map is 16-bit(The only ones I've seen) per key,
数据可能是混合数据,例如看看 Adobe CMap and CIDFont Files Specification ,这里的 CMap 示例 9 包含部分
4 begincodespacerange
<00> <80>
<8140> <9ffc>
<a0> <de>
<e040> <fbec>
endcodespacerange
解释为
Figure 6 shows how the codespace definition in this example comprises two single-byte linear ranges of codes (
<00>
to<80>
and<A0>
to<DF>
) and two double-byte rectangular ranges of codes (<8140>
to<9FFC>
and<E040>
to<FBFC>
). The first two-byte region comprises all codes bounded by first-byte values of 81 through 9F and second-byte values of 40 through FC. Thus, the input code<86A9>
is within the region because both bytes are within bounds. That code is valid. The input code<8210>
is not within the region, even though its first byte is between 81 and 9F, because its second byte is not within bounds. That code is invalid. The second two-byte region is similarly bounded.
关于java - 阅读 PDF Literal String 解析困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26351052/