在VB.NET或C#中使用itextsharp dll读取PDF内容

83

我该如何使用itextsharp的Pdfreader类读取PDF内容。我的PDF文件可能包含纯文本或文字图像。


iTextSharp现在被称为“iText 7 for .NET”或“itext7-dotnet”,可以在github上找到:链接。建议使用Nuget将itext7添加到您的解决方案中。 - Peter Huber
6个回答

193
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using System.IO;

public string ReadPdfFile(string fileName)
{
    StringBuilder text = new StringBuilder();

    if (File.Exists(fileName))
    {
        PdfReader pdfReader = new PdfReader(fileName);

        for (int page = 1; page <= pdfReader.NumberOfPages; page++)
        {
            ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
            string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);

            currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
            text.Append(currentText);
        }
        pdfReader.Close();
    }
    return text.ToString();
}

1
为什么pdfReader.Close();在for循环内部执行? - Th 00 mÄ s
10
дЄЇдїАдєИйЬАи¶БдљњзФ®.Close()пЉМиАМдЄНжШѓusing (var pdfReader = ...) {}пЉЯ - Sebastian
2
另外,ASCIIEncoding.Convert 应该改为 Encoding.Convert,因为它是一个静态方法。 - Sebastian

17

LGPL / FOSS iTextSharp 4.x

var pdfReader = new PdfReader(path); //other filestream etc
byte[] pageContent = _pdfReader .GetPageContent(pageNum); //not zero based
byte[] utf8 = Encoding.Convert(Encoding.Default, Encoding.UTF8, pageContent);
string textFromPage = Encoding.UTF8.GetString(utf8);

没有其他答案对我有用,它们似乎都针对iTextSharp的AGPL v5。在FOSS版本中,我从未找到任何与SimpleTextExtractionStrategy或LocationTextExtractionStrategy有关的参考。
这可能非常有用的另一件事是:
const string PdfTableFormat = @"\(.*\)Tj";
Regex PdfTableRegex = new Regex(PdfTableFormat, RegexOptions.Compiled);

List<string> ExtractPdfContent(string rawPdfContent)
{
    var matches = PdfTableRegex.Matches(rawPdfContent);

    var list = matches.Cast<Match>()
        .Select(m => m.Value
            .Substring(1) //remove leading (
            .Remove(m.Value.Length - 4) //remove trailing )Tj
            .Replace(@"\)", ")") //unencode parens
            .Replace(@"\(", "(")
            .Trim()
        )
        .ToList();
    return list;
}

这将从PDF中提取仅包含文本的数据。如果显示的文本是Foo(bar),那么它在PDF中将被编码为(Foo\(bar\))Tj,该方法将返回预期的Foo(bar)。此方法将从原始PDF内容中剥离出许多其他信息,例如位置坐标。

1
你说得对,在5.x.x版本之前,iText中的文本提取仅作为概念验证存在,并且在iTextSharp中根本不存在。话虽如此,您提供的代码仅适用于非常原始的PDF(使用ASCII编码的字体和Tj作为唯一的文本绘制运算符)。它可能在非常受控制的环境中可用(您可以确保只获取这种原始的PDF),但不适用于一般情况。 - mkl
正确的正则表达式是:(?<=()(.*?)(?=) Tj) - Diego

8

这是基于ShravankumarKumar方案的VB.NET解决方案。

这仅会给您文本内容。图片需要另行处理。

Public Shared Function GetTextFromPDF(PdfFileName As String) As String
    Dim oReader As New iTextSharp.text.pdf.PdfReader(PdfFileName)

    Dim sOut = ""

    For i = 1 To oReader.NumberOfPages
        Dim its As New iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy

        sOut &= iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(oReader, i, its)
    Next

    Return sOut
End Function

当我在我的PDF上尝试这样做时,它会给我一个错误消息:"值不能为空。参数名称:值"。有什么想法吗? - Avi
sOut &= iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(oReader, i, its).同时,我已经弄清楚了有关此错误的某些信息。如果我将其从循环中取出并解析单个页面,则在一个页面上可以工作,而在另一个页面上则不能。我能看到的两者之间唯一的区别是有问题的页面上有图像(我不需要)。 - Avi
如果您想查看PDF文件,我可以将其发送给您。 - Avi
我正在使用 .Net 4.0 和 itextsharp 5.1.2.0(刚刚下载)。你也是这样吗? - Carter Medlin
.Net 3.5和itextsharp 5.1.1。我会更新并查看是否已解决。 - Avi

5
在我的情况下,我只想要从PDF文档的特定区域获取文本,因此我在该区域周围使用了一个矩形,并从中提取了文本。在下面的示例中,坐标是针对整个页面的。由于我没有PDF作者工具,所以在缩小矩形到特定位置时,我尝试了几次猜测坐标,直到找到所需的区域为止。
Rectangle _pdfRect = new Rectangle(0f, 0f, 612f, 792f); // Entire page - PDF coordinate system 0,0 is bottom left corner.  72 points / inch
RenderFilter _renderfilter = new RegionTextRenderFilter(_pdfRect);
ITextExtractionStrategy _strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), _filter);
string _text = PdfTextExtractor.GetTextFromPage(_pdfReader, 1, _strategy);

正如上面的评论所指出的那样,生成的文本不保留PDF文档中的任何格式,但我很高兴它确实保留了回车符。在我的情况下,文本中有足够的常量,我能够提取所需的值。


1

这里是ShravankumarKumar的改进答案。我创建了特殊的类用于页面,因此您可以基于文本行和该行中的单词访问pdf中的单词。

using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

//create a list of pdf pages
var pages = new List<PdfPage>();

//load the pdf into the reader. NOTE: path can also be replaced with a byte array
using (PdfReader reader = new PdfReader(path))
{
    //loop all the pages and extract the text
    for (int i = 1; i <= reader.NumberOfPages; i++)
    {
        pages.Add(new PdfPage()
        {
           content = PdfTextExtractor.GetTextFromPage(reader, i)
        });
    }
}

//use linq to create the rows and words by splitting on newline and space
pages.ForEach(x => x.rows = x.content.Split('\n').Select(y => 
    new PdfRow() { 
       content = y,
       words = y.Split(' ').ToList()
    }
).ToList());

自定义类
class PdfPage
{
    public string content { get; set; }
    public List<PdfRow> rows { get; set; }
}


class PdfRow
{
    public string content { get; set; }
    public List<string> words { get; set; }
}

现在您可以按行和单词索引获取单词。
string myWord = pages[0].rows[12].words[4];

或者使用Linq查找包含特定单词的行。

//find the rows in a specific page containing a word
var myRows = pages[0].rows.Where(x => x.words.Any(y => y == "myWord1")).ToList();

//find the rows in all pages containing a word
var myRows = pages.SelectMany(r => r.rows).Where(x => x.words.Any(y => y == "myWord2")).ToList();

-2
Public Sub PDFTxtToPdf(ByVal sTxtfile As String, ByVal sPDFSourcefile As String)
        Dim sr As StreamReader = New StreamReader(sTxtfile)
    Dim doc As New Document()
    PdfWriter.GetInstance(doc, New FileStream(sPDFSourcefile, FileMode.Create))
    doc.Open()
    doc.Add(New Paragraph(sr.ReadToEnd()))
    doc.Close()
End Sub

1
问题是要求阅读PDF文件,而你的答案却是创建一个! - AaA

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