如何用C#读取PDF中手动添加的文本?iTextSharp读取失败解决方案
解决iTextSharp无法读取PDF手动添加文本的问题
你遇到的核心问题是:通过FoxIt Reader、Nuance PDF等工具手动添加的文本,大多以**PDF表单域(Form Field)或注释(Annotation)**的形式存储,而默认的LocationTextExtractionStrategy只会提取页面内容流中的原生文本,不会处理这些附加元素。以下是具体解决思路:
1. 提取表单域中的文本
很多PDF编辑器添加的文本会被保存为表单域,可通过AcroFields对象遍历读取:
string parsedText = string.Empty; using (PdfReader reader = new PdfReader(pdfPath)) { // 提取页面原生文本 ITextExtractionStrategy its = new LocationTextExtractionStrategy(); parsedText = PdfTextExtractor.GetTextFromPage(reader, 1, its); // 提取表单域文本 AcroFields fields = reader.AcroFields; foreach (string fieldName in fields.Fields.Keys) { string fieldValue = fields.GetField(fieldName); if (!string.IsNullOrEmpty(fieldValue)) { // 将表单域文本追加到结果中,或单独处理目标发票编号 parsedText += "\n" + fieldValue; // 可根据字段名或值特征筛选发票编号,比如字段名包含"InvoiceNo"等 } } }
2. 提取注释中的文本
如果文本是以自由文本注释(FreeText)或普通文本注释(Text)形式添加的,需要遍历页面的注释集合:
using (PdfReader reader = new PdfReader(pdfPath)) { for (int pageNum = 1; pageNum <= reader.NumberOfPages; pageNum++) { PdfDictionary pageDict = reader.GetPageN(pageNum); PdfArray annots = pageDict.GetAsArray(PdfName.ANNOTS); if (annots == null) continue; foreach (PdfObject annotObj in annots.ArrayList) { PdfDictionary annotDict = (PdfDictionary)PdfReader.GetPdfObject(annotObj); PdfName subtype = annotDict.GetAsName(PdfName.SUBTYPE); // 处理自由文本注释(常见的手动添加文本类型) if (PdfName.FREETEXT.Equals(subtype)) { PdfString content = annotDict.GetAsString(PdfName.CONTENTS); if (content != null) { string annotText = content.ToUnicodeString(); // 处理注释文本,比如匹配发票编号格式 } } // 处理普通文本注释(便签类) else if (PdfName.TEXT.Equals(subtype)) { PdfString content = annotDict.GetAsString(PdfName.CONTENTS); if (content != null) { string annotText = content.ToUnicodeString(); // 处理注释文本 } } } } }
3. 优化编码处理
你原代码中的编码转换是冗余的,iTextSharp的GetTextFromPage和ToUnicodeString已经处理了Unicode编码,直接使用即可避免乱码问题。
注意事项
- 不同PDF编辑器的文本存储逻辑可能不同,建议先通过PDF分析工具(如iText RUPS)查看目标文本的存储类型(表单域/注释),再针对性处理。
- 可通过正则表达式匹配发票编号的格式(比如固定长度数字、前缀+数字等),快速定位目标内容。
内容的提问来源于stack exchange,提问作者Helyx
相关产品推荐
相关产品推荐

