You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:30:12