使用iText7提取特定来源PDF文本返回0xfdff乱码的问题咨询
iText7提取特定PDF文本返回0xfdff乱码问题
问题现象
使用iText7提取PDF文档文本时,特定来源文档在自定义文本提取策略的事件处理方法中,调用textRenderInfo.GetText()仅返回乱码字符0xfdff。
使用的自定义文本提取策略代码如下:
internal class CustomExtractionStrategy : ITextExtractionStrategy { public virtual void EventOccurred(IEventData data, EventType type) { if (!type.Equals((object)EventType.RENDER_TEXT)) { return; } var textRenderInfo = (TextRenderInfo)data; bool currentResultEmpty = _result.Length == 0; bool isInNewLine = false; var baseline = textRenderInfo.GetBaseline(); var startPoint = baseline.GetStartPoint(); var endPoint = baseline.GetEndPoint(); var currentText = textRenderInfo.GetText(); // 特定PDF下此处返回乱码 // 后续处理逻辑 ... } }
已排查特征
对比可正常提取的PDF样例,问题PDF存在以下明确差异:
textRenderInfo.gs.font对应字体为 MS-UIGothictextRenderInfo.gs.font.fontProgram.codeToGlyph仅包含1条映射关系:键为0,对应宽度1000、unicode属性为-1、code属性为0的Glyph对象textRenderInfo.gs.font.fontProgram.unicodeToGlyph无任何映射记录
补充信息
- 问题PDF可在Acrobat Reader中正常浏览,支持从阅读器直接复制文本到记事本
- 其他PDF处理类库(基于pdfium的实现、PDFBox移植版本)均可正常提取该文档文本,文档本身为符合规范的有效文件
- 因文档包含不得对外披露的敏感信息,无法提供问题PDF样例
- 参考相关建议补充调用代码后,提取结果仍为乱码,补充的调用代码如下:
internal class PdfExtractor { internal void ExtractFromPath(string path) { PdfReader reader = new PdfReader(path); var document = new iText.Kernel.Pdf.PdfDocument(reader); for (int pageNum = 1; pageNum <= document.GetNumberOfPages(); pageNum++) { var page = document.GetPage(pageNum); string text = PdfTextExtractor.GetTextFromPage(page, new CustomExtractionStrategy()); } } }
待确认问题
- 该现象是否为iText7的已知问题?
- 除更换其他类库外,是否存在可行的解决方案?
解答
0xfdff是iText内置的替换字符,当无法匹配字形对应的Unicode编码时就会返回该值,和你观察到的字体映射表为空的现象完全对应。
该问题是iText7对部分内嵌子集化日文字体(你遇到的MS-UIGothic属于典型场景)的已知兼容缺陷,并非PDF文件损坏,可按以下优先级尝试修复:
- 升级iText7到最新稳定版本
7.1.x早期版本对部分ToUnicode CMap表存储格式非标准的字体存在Unicode映射加载失败的bug,7.2及之后版本修复了绝大多数MS系列日文字体的提取兼容问题,优先升级版本验证。 - 显式注册系统字体作为兜底
若升级后问题仍存在,可在初始化PdfReader前,将系统中安装的完整MS-UIGothic字体注册到iText字体缓存,iText检测到内嵌字体映射缺失时,会自动 fallback 到同名系统字体完成编码映射:// 程序初始化时执行一次即可 FontProgramFactory.RegisterFont("C:\\Windows\\Fonts\\msuigothic.ttc", "MS-UIGothic"); - 手动解析ToUnicode映射
如果上述方案无效,可扩展自定义提取策略的编码解析逻辑:直接读取当前文本块对应PDF字体字典中的ToUnicode流,手动解析CMap映射关系,替换GetText()默认的映射逻辑。iText默认逻辑在字体codeToGlyph表为空时会直接返回0xfdff占位符,手动解析ToUnicode流可以绕过这个错误返回逻辑。
验证时不要使用iText默认的
LocationTextExtractionStrategy做对照,该类和自定义策略共用同一套字体映射逻辑,字体加载失败时会返回完全相同的乱码。
内容的提问来源于stack exchange,提问作者unstone
相关产品推荐
相关产品推荐

