使用iText7读取PDF ASCII文本返回乱码,如何解决?
解决iText7读取PDF乱码问题及替代方案
一、iText7配置调整方案
你当前代码中未明确初始化strategy变量,这大概率是乱码的核心原因。默认文本提取策略无法适配部分PDF的自定义字体编码或非标准字体映射,可通过以下方式调整:
1. 显式使用标准提取策略并排查字体编码
先尝试用SimpleTextExtractionStrategy或LocationTextExtractionStrategy显式初始化,同时打印字体编码信息排查问题:
var pdfDocument = new PdfDocument(new PdfReader("你的PDF路径")); StringBuilder processed = new StringBuilder(); for (int i = 1; i <= pdfDocument.GetNumberOfPages(); ++i) { var page = pdfDocument.GetPage(i); // 显式使用位置文本提取策略 var strategy = new LocationTextExtractionStrategy(); string text = PdfTextExtractor.GetTextFromPage(page, strategy); processed.Append(text); // 打印当前页字体编码,排查异常 var fonts = page.GetResources().GetFonts(); foreach (var fontEntry in fonts) { var pdfFont = fontEntry.Value.GetFont(); Console.WriteLine($"字体编码: {pdfFont.GetEncoding()}"); } }
2. 自定义渲染监听器处理编码转换
若发现字体使用非标准编码,可自定义监听器强制转换编码:
public class CustomTextStrategy : ITextExtractionStrategy { private readonly StringBuilder _result = new(); public void BeginTextBlock() { } public void EndTextBlock() { } public void RenderImage(ImageRenderInfo renderInfo) { } public void RenderText(TextRenderInfo renderInfo) { var rawText = renderInfo.GetText(); // 尝试将默认编码转换为ASCII/UTF-8,过滤无效字符 var cleanedText = Encoding.ASCII.GetString( Encoding.Convert(Encoding.Default, Encoding.ASCII, Encoding.Default.GetBytes(rawText)) ); _result.Append(cleanedText); } public string GetResultantText() => _result.ToString(); } // 使用自定义策略 var strategy = new CustomTextStrategy(); string text = PdfTextExtractor.GetTextFromPage(page, strategy);
3. 处理特殊压缩/加密PDF
如果PDF使用特殊压缩或加密,需配置读取器参数:
var readerProps = new ReaderProperties(); readerProps.SetUnethicalReading(true); // 解锁特殊压缩/加密的PDF读取权限 var pdfDocument = new PdfDocument(new PdfReader("你的PDF路径", readerProps));
二、替代PDF读取库推荐
若iText7调整后仍无法解决,以下库在复杂PDF文本提取上表现更稳定:
1. PdfSharp
轻量级开源库,对编码兼容性较好:
using PdfSharp.Pdf; using PdfSharp.Pdf.Content; using PdfSharp.Pdf.Content.Objects; var document = PdfReader.Open("你的PDF路径"); StringBuilder text = new(); foreach (PdfPage page in document.Pages) { var reader = ContentReader.ReadContent(page); reader.Visit(new ContentVisitor(text)); } public class ContentVisitor : IContentVisitor { private readonly StringBuilder _text; public ContentVisitor(StringBuilder text) => _text = text; public void Visit(CObject obj) { if (obj is CString str) _text.Append(str.Value); else if (obj is CSequence seq) { foreach (var child in seq) child.Visit(this); } } }
2. Syncfusion PDF Library
商业库(提供免费社区版),对复杂字体、子集化字体的支持完善:
using Syncfusion.Pdf.Parsing; var loadedDoc = new PdfLoadedDocument("你的PDF路径"); StringBuilder text = new(); foreach (PdfLoadedPage page in loadedDoc.Pages) { text.Append(page.ExtractText()); }
3. Tesseract OCR(针对图像型PDF)
若PDF是扫描生成的图像格式(即便能复制,可能是隐藏OCR文本),可转图像后用OCR提取:
using Tesseract; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas.Parser.Listener; // 先将PDF页转为图像 var pdfDoc = new PdfDocument(new PdfReader("你的PDF路径")); var page = pdfDoc.GetPage(1); var imgRenderer = new PdfCanvasProcessor(new ImageRenderListener()); imgRenderer.ProcessPageContent(page); // 用Tesseract提取图像文本 using var engine = new TesseractEngine(@"tessdata", "eng", EngineMode.Default); using var pix = Pix.LoadFromFile("生成的图像路径.png"); using var ocrPage = engine.Process(pix); var text = ocrPage.GetText();
三、额外排查点
- 检查PDF是否使用子集化字体:子集化字体仅嵌入部分字符,需确保字体编码表完整,可尝试用Adobe Acrobat导出完整字体后重新测试。
- 验证PDF文本是否为隐藏层文本:部分PDF会在图像层下嵌入OCR文本,需确保提取策略能读取隐藏内容。
内容的提问来源于stack exchange,提问作者Andrus
相关产品推荐
相关产品推荐

