C#使用PdfSharp提取PDF文本

65

有没有可能使用PdfSharp从PDF文件中提取纯文本?我不想使用iTextSharp因为它的许可证。


10
不知道为什么会有负分?(没有澄清问题并帮助作者改进的评论。) - TN.
你需要从文档中提取ToUnicode CMaps以转换文本字符串的二进制索引,除非你很幸运,二进制索引本身就是ASCII值。 - R.J. Dunnill
4个回答

57

参考Sergio的答案,并创建了一些扩展方法。同时将字符串的累加改为了迭代器。

public static class PdfSharpExtensions
{
    public static IEnumerable<string> ExtractText(this PdfPage page)
    {       
        var content = ContentReader.ReadContent(page);      
        var text = content.ExtractText();
        return text;
    }   

    public static IEnumerable<string> ExtractText(this CObject cObject)
    {   
        if (cObject is COperator)
        {
            var cOperator = cObject as COperator;
            if (cOperator.OpCode.Name== OpCodeName.Tj.ToString() ||
                cOperator.OpCode.Name == OpCodeName.TJ.ToString())
            {
                foreach (var cOperand in cOperator.Operands)
                    foreach (var txt in ExtractText(cOperand))
                        yield return txt;   
            }
        }
        else if (cObject is CSequence)
        {
            var cSequence = cObject as CSequence;
            foreach (var element in cSequence)
                foreach (var txt in ExtractText(element))
                    yield return txt;
        }
        else if (cObject is CString)
        {
            var cString = cObject as CString;
            yield return cString.Value;
        }
    }
}

我正在使用PDFsharp库,但它显示ContentReader类上下文无效。可能是什么问题? - Sudarshan Taparia
ContentReader类上下文不明确。 - Ronnie Overby
6
无法抵制。我不知道那是什么意思,也不知道该如何解决。我尽量避免使用 PDF 文件,因为处理它们的工具很差,并且假装人类可读格式是机器可读的是彻头彻尾的愚蠢行为。 - Ronnie Overby
1
PdfSharp v1.32.3057 存在一个 bug,即 ContentReader.ReadContent 会挂起。为了修复此问题,需要进行一些更改(请参见此处)。修复该 bug 后,我可以确认它已经解决了。 :-) - Nicholas Miller
3
虽然这很有前途,但并不适用于Unicode文本。 - NoOne
显示剩余4条评论

22

我以某种方式实现了它,类似于David的方式。这是我的代码:

...
{
    // ....
    var page = document.Pages[1];
    CObject content = ContentReader.ReadContent(page);
    var extractedText = ExtractText(content);
    // ...
}

private IEnumerable<string> ExtractText(CObject cObject)
{
    var textList = new List<string>();
    if (cObject is COperator)
    {
        var cOperator = cObject as COperator;
        if (cOperator.OpCode.Name == OpCodeName.Tj.ToString() ||
            cOperator.OpCode.Name == OpCodeName.TJ.ToString())
        {
            foreach (var cOperand in cOperator.Operands)
            {
                textList.AddRange(ExtractText(cOperand));
            }
        }
    }
    else if (cObject is CSequence)
    {
        var cSequence = cObject as CSequence;
        foreach (var element in cSequence)
        {
            textList.AddRange(ExtractText(element));
        }
    }
    else if (cObject is CString)
    {
        var cString = cObject as CString;
        textList.Add(cString.Value);
    }
    return textList;
}

1
你不应该削减 StringBuilder,PDF 文件相当大,这种解决方案会导致巨大的不必要的内存消耗。 - Ivan Ičin

14

PDFSharp提供了从PDF中提取文本的所有工具。使用ContentReader类访问每个页面中的命令,并从TJ/Tj运算符中提取字符串。

我已经将一个简单的实现上传到github上。


7
在许多PDF文件中,CString.Value返回一些无用的数据(例如使用OpenOffice.org创建PDF文件并尝试使用此方法导入时)。 - Ivan Ičin
2
不,PdfSharp并没有提供所有的文本提取工具。目前还需要添加ToUnicode CMaps功能,这是提取Unicode PDF文本所必需的。 - R.J. Dunnill
1
因为那是我做出的选择。 - David Schmitt
似乎并不完美,一个单词可能会被分成几行,例如:预 测是很常见的。 - hazjack
@hazjack 是的,你需要一个强大的人工智能来从你的PDF中恢复文本。 - David Schmitt

-1
使用这种方法,我最近实际上弄清楚了如何为你们所称的Unicode做到这一点。但它并不完全是Unicode,而是PdfEncoding。嵌入式字体会导致PDF生成不同的表格,称为CMaps,您必须存储并交换pdfEncoding Unicode值,直到在cmap表中找到一个并将其放置在那里。我将符号转换为可读文本,这需要学习PDF文件结构3周时间。您还需要使用sharpZipLib来解压缩cmap表格,因为它们是压缩的。

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Viktor Liehr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接