Java 通过pdfbox从pdf文档中提取文本时没有Unicode映射错误,因为字体dict中缺少ToUnicode CMap条目

Java 通过pdfbox从pdf文档中提取文本时没有Unicode映射错误,因为字体dict中缺少ToUnicode CMap条目,java,pdfbox,Java,Pdfbox,Adobe Acrobat Pro“内容视图”显示字符正常,但当我复制和粘贴时,字符无效。但如果“使用格式化复制”,则显示字符正常 例如“第一个字母”重", 当我使用pdfbox提取字母时,会出现一些警告警报 一月 08, 2021 11:14:37 上午 org.apache.pdfbox.pdmodel.font.PDType0Font toUnicode 警告: No Unicode mapping for CID+18429 (18429) in font GVAQVQ+SimSun

Adobe Acrobat Pro“内容视图”显示字符正常,但当我复制和粘贴时,字符无效。但如果“使用格式化复制”,则显示字符正常

例如“第一个字母”重", 当我使用pdfbox提取字母时,会出现一些警告警报

一月 08, 2021 11:14:37 上午 org.apache.pdfbox.pdmodel.font.PDType0Font toUnicode
警告: No Unicode mapping for CID+18429 (18429) in font GVAQVQ+SimSun
PDFont.LoadUnicodeMap()因为在font GVAQVQ+SimSun中没有ToUnicode CMap条目,所以PDType0Font.ToUnicodeMap为null。所以当调用PDFont.ToUnicode()时,它返回null

@mkl如果有办法解决此问题,请提前感谢。

PDType0Font/null, PostScript name: GVAQVQ+SimSun

   0 = {SmallMap$SmallMapEntry@2123} "COSName{BaseFont}" -> "COSName{GVAQVQ+SimSun}"
   1 = {SmallMap$SmallMapEntry@2124} "COSName{DescendantFonts}" -> "COSArray{[COSDictionary{COSName{BaseFont}:COSName{GVAQVQ+SimSun};COSName{CIDSystemInfo}:COSDictionary{COSName{Ordering}:COSString{Identity};COSName{Registry}:COSString{PDFXC30};COSName{Supplement}:COSInt{0};};COSName{DW}:COSInt{1000};COSName{FontDescriptor}:COSObject{COSDictionary{COSName{Ascent}:COSInt{859};COSName{AvgWidth}:COSInt{500};COSName{CapHeight}:COSInt{668};COSName{Descent}:COSInt{-141};COSName{Flags}:COSInt{32};COSName{FontBBox}:COSArray{COSInt{-8};COSInt{-145};1000;859;};COSName{FontFile2}:COSObject{COSDictionary{COSName{Length}:COSInt{175201};COSName{Filter}:COSArray{COSName{FlateDecode};};COSName{Length1}:COSInt{468544};}COSStream{-708342007}};COSName{FontName}:-120083354;COSName{ItalicAngle}:0;COSName{Leading}:COSInt{141};COSName{MaxWidth}:1000;COSName{MissingWidth}:500;COSName{StemH}:COSInt{70};COSName{StemV}:70;COSName{Type}:COSName{FontDescriptor};COSName{XHeight}:COSInt{438};}};COSName{Subtype}:COSName{CIDFontType2};COSName{Type}:COSNa
   2 = {SmallMap$SmallMapEntry@2125} "COSName{Encoding}" -> "COSName{Identity-H}"
   3 = {SmallMap$SmallMapEntry@2126} "COSName{Subtype}" -> "COSName{Type0}"
   4 = {SmallMap$SmallMapEntry@2127} "COSName{Type}" -> "COSName{Font}"

"COSName{FontDescriptor}" -> "COSObject{15, 0}"
key = {COSName@2168} "COSName{FontDescriptor}"
value = {COSObject@2169} "COSObject{15, 0}"
baseObject = {COSDictionary@2209} "COSDictionary{COSName{Ascent}:COSInt{859};COSName{AvgWidth}:COSInt{500};COSName{CapHeight}:COSInt{668};COSName{Descent}:COSInt{-141};COSName{Flags}:COSInt{32};COSName{FontBBox}:COSArray{COSInt{-8};COSInt{-145};COSInt{1000};859;};COSName{FontFile2}:COSObject{COSDictionary{COSName{Length}:COSInt{175201};COSName{Filter}:COSArray{COSName{FlateDecode};};COSName{Length1}:COSInt{468544};}COSStream{-708342007}};COSName{FontName}:COSName{GVAQVQ+SimSun};COSName{ItalicAngle}:COSInt{0};COSName{Leading}:COSInt{141};COSName{MaxWidth}:1000;COSName{MissingWidth}:500;COSName{StemH}:COSInt{70};COSName{StemV}:70;COSName{Type}:COSName{FontDescriptor};COSName{XHeight}:COSInt{438};}"
needToBeUpdated = false
items = {SmallMap@2211}  size = 16
0 = {SmallMap$SmallMapEntry@2214} "COSName{Ascent}" -> "COSInt{859}"
1 = {SmallMap$SmallMapEntry@2215} "COSName{AvgWidth}" -> "COSInt{500}"
2 = {SmallMap$SmallMapEntry@2216} "COSName{CapHeight}" -> "COSInt{668}"
3 = {SmallMap$SmallMapEntry@2217} "COSName{Descent}" -> "COSInt{-141}"
4 = {SmallMap$SmallMapEntry@2218} "COSName{Flags}" -> "COSInt{32}"
5 = {SmallMap$SmallMapEntry@2219} "COSName{FontBBox}" -> "COSArray{[COSInt{-8}, COSInt{-145}, COSInt{1000}, COSInt{859}]}"
6 = {SmallMap$SmallMapEntry@2220} "COSName{FontFile2}" -> "COSObject{12, 0}"
7 = {SmallMap$SmallMapEntry@2221} "COSName{FontName}" -> "COSName{GVAQVQ+SimSun}"
8 = {SmallMap$SmallMapEntry@2222} "COSName{ItalicAngle}" -> "COSInt{0}"
9 = {SmallMap$SmallMapEntry@2223} "COSName{Leading}" -> "COSInt{141}"
10 = {SmallMap$SmallMapEntry@2224} "COSName{MaxWidth}" -> "COSInt{1000}"
11 = {SmallMap$SmallMapEntry@2225} "COSName{MissingWidth}" -> "COSInt{500}"
12 = {SmallMap$SmallMapEntry@2226} "COSName{StemH}" -> "COSInt{70}"
13 = {SmallMap$SmallMapEntry@2227} "COSName{StemV}" -> "COSInt{70}"
14 = {SmallMap$SmallMapEntry@2228} "COSName{Type}" -> "COSName{FontDescriptor}"
15 = {SmallMap$SmallMapEntry@2229} "COSName{XHeight}" -> "COSInt{438}"

PDFBox文本提取根据PDF规范ISO 32000-1第9.10.2节“将字符代码映射到Unicode值”中介绍的算法工作。尝试将此算法应用于文件时,无法提取使用SimSun字体嵌入子集(F2)绘制的文本:

  • “如果字体词典包含ToUnicodeCMap”-F2没有ToUnicodeCMap
  • “如果字体是简单字体”-F2不是简单字体
  • “如果字体是复合字体“-F2确实是复合字体,但是。。。
    • “使用表118中列出的预定义CMAP之一(身份–H和身份–V除外)”-F2使用Identity-H
    • “或其子代CIDFont使用Adobe-GB1、Adobe-CNS1、Adobe-Japan1或Adobe-Korea1字符集合的用户”-F2使用PDFXC30标识字符集合
  • 如果这些方法无法生成Unicode值,则无法确定字符代码所代表的内容,在这种情况下,一致性读取器可以选择自己选择的字符代码
因此,在PDFBox中实现的文本提取无法提取该中文文本

PDF规范中提供的文本提取期间文本信息的另一个来源是结构元素或标记内容序列的ActualText条目。但您的PDF也没有任何此类ActualText条目

因此,Adobe Acrobat copy&paste(使用前面提到的算法和ActualText分析的组合)无法提取该中文文本

因此,Adobe Acrobat Pro中的“带格式复制”显然必须使用PDF规范所建议的机制之外的一些信息

检查嵌入式字体资源本身,可以看到它既不包含自己的Unicode映射,也不包含任何标准名称。但是,值得注意的是,字形编号不是连续编号的,而是有间隙的。这些数字可能是在子集设置期间从完整字体保留的

因此,Adobe Acrobat Pro在中文文本的“格式化复制”过程中似乎会执行以下任一选项:

  • 他们知道PDFXC30身份字符集合的详细信息,无论是通过PDF XChange还是通过反向工程,并使用该信息进行提取
  • (如果假设在子集设置期间完整字体中保留了字形编号是正确的:)它们知道SimSun字体,并且具有用于提取的字形编号到Unicode的映射
  • 他们获取SimSun字体的完整副本(内部提供或由主机操作系统提供),将其中的字形与嵌入子集中的字形进行比较,并从中导出到Unicode的映射,用于文本提取
  • 他们将OCR应用于嵌入字体的各个字形,并从结果中导出到Unicode的映射
通过谷歌搜索PDFXC30身份字符集,可以发现有许多文本提取工具存在问题,例如,在Aspose论坛上可以阅读:

我们的团队已经研究了这个问题,我想与您分享,您用来创建样本PDF文件的软件使用PDFXC30字符集。这个字符集不是标准的,我们没有关于这个编码的任何信息。这使得目前无法正确提取文本

(shahzadlatif在线程中的最新响应)


如果您可以从可靠的来源提供PDFXC30字符集合映射文件,PDFBox开发可能会将它们包含到PDFBox中,以便为您这样的文件启用文本提取。

@mkl寻求帮助感谢您的快速响应,帮助我了解PDFBox文本提取的方式。我尝试抓住机会找到PDFXC30字符。Th再次感谢你!