我从使用 Ghostscript 9.19 创建 PDF/A 兼容 PDF (1.4) 的客户那里获得的 PDF 存在特殊问题。我想使用 LocationTextExtractionStrategy 从中提取文本,但我以相反的顺序获取大部分文本并带有额外的空格:
期待:abc
获得:cba
在内容流中,这可能是 [a,1,b,1,c] TJ
这个问题之前已经发布到 Stackoverflow,但是我比破解我自己的提取策略更进一步解决了这个问题。我意识到所使用字体的字体宽度全为零,并且度量值和 hMetrics 映射均未填充。我使用的是 iTextSharp 5.5.4,但 5.5.9 仍然有同样的问题。
这是字体:
/Subtype /Type0
/BaseFont /VGOQEA+SegoeUI
/Type /Font
/Encoding 33 0 R
/ToUnicode 48 0 R
/DescendantFonts [35 0 R]
对象 33 是一个 CMap:
/CIDSystemInfo 32 0 R
/Filter /FlateDecode
/Length 266
/CMapName /OneByteIdentityH
/Type /CMap
对象 48 是一个 Stream,顺便说一下也是一个 CMap
对象 35 终于有了一些宽度定义
/DW 539
/CIDSystemInfo 32 0 R
/Subtype /CIDFontType2
/BaseFont /VGOQEA+SegoeUI
/FontDescriptor 26 0 R
/Type /Font
/W [0, [646], 32, [274], 40, [302, 302], 44, [217, 400, 217], 48, [539, 539, 539, 539], 53, [539, 539, 539, 539], 58, [217], 64, [955, 645, 573], 68, [701, 506], 72, [710, 266], 75, [580, 471, 898], 80, [560], 82, [598, 531], 85, [687], 87, [934], 90, [570], 97, [509, 588, 462, 589, 523, 313, 589, 566, 242], 107, [497, 242, 861, 566, 586, 588], 114, [348, 424, 339, 566], 119, [723], 122, [452], 220, [687], 228, [509], 246, [586], 252, [566]]
/CIDToGIDMap 47 0 R
按照 iTextSharp 初始化 CMapAwareDocumentFont 的顺序,首先初始化基本 DocumentFont。然后构造函数检查:
if (PdfName.TYPE1.Equals(subType) || PdfName.TRUETYPE.Equals(subType))
两者都不是。
else if (PdfName.TYPE3.Equals(subType))
它不是。然后进入下一个else分支:
PdfName encodingName = font.GetAsName(PdfName.ENCODING);
if (encodingName == null)
但由于编码是作为间接引用给出的,因此 encodingName 为空。因此,永远不会处理此 Type0 字体的处理。
我在库代码中更改了这一点,但即使调用了 ProcessType0(font) 方法,宽度值也从未进入字体定义 - 即全部保持为零。这可能是意料之中的。最后我得到了填充的指标哈希映射,但我没有涵盖所有使用的字符。即情况有所好转,但并非一切都好:
而不是: abc -> cba
我现在得到: abc -> acb
对于当前问题,我唯一可行但很老套的解决方案是破解 processor.DisplayPdfString((PdfString)entryObj) 以将 textMatrix 调整固定数量。然而,这不是一般的解决方案,我宁愿字体能正常工作。任何其他建议我应该尝试什么?
编辑:我使用 iText 7 .Net 重新审视了我的问题,现在在尝试从我的测试文件中读取文本时出现 NullReferenceException。
var reader = new iText.Kernel.Pdf.PdfReader(@"itextsharp_sample_locationtext_extraction_reversing_characters(1).pdf");
var extractionStrategy = new LocationTextExtractionStrategy();
var doc = new PdfDocument(reader);
var page = doc.GetFirstPage();
var test = PdfTextExtractor.GetTextFromPage(doc.GetFirstPage());
Console.WriteLine(test);
这是我使用的文件:https ://drive.google.com/file/d/0B1RdIg0_Pbd_aTlOT2VmbnFlaTQ/view?usp=sharing
该代码适用于其他 PDF 文件,但不适用于这个。
更新 感谢 mkl,我现在知道了一段时间,根本问题是字体编码流。遗憾的是,我刚刚通过 iText 销售团队收到一条消息,说这不在路线图上。他们声称这是一个奇怪的异常值,大多数其他人不需要对字体编码流的支持。因此,如果您在阅读本文时确实遇到了缺少支持的问题,请通过电子邮件告知他们。