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


80

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


iTextSharp现在在github:link上称为“ iText 7 for .NET”或“ itext7-dotnet” 。建议将带有Nuget的itext7添加到您的解决方案中。
Peter Huber

Answers:


184
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();
}

16
这应该标记为解决方案!这对我来说很棒。
卡特梅德林

1
pdfReader.Close()的任何特殊原因;发生在for循环内?
00 00年

8
为什么根本不使用.Close()using (var pdfReader = ...) {}
塞巴斯蒂安

2
另外,ASCIIEncoding.Convert应该Encoding.Convert是一种静态方法
Sebastian

如果有人需要类似于上述代码的代码,请逐步执行以C#读取pdf文本,这是链接qawithexperts.com/article/c-sharp / ...谢谢
user3559462

15

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。我永远找不到任何引用SimpleTextExtractionStrategyLocationTextExtractionStrategy在FOSS版本中。

与此结合可能会非常有用的其他一些东西:

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;
}

如果显示的文本Foo(bar)将在PDF中编码为,则将从PDF中提取纯文本数据(Foo\(bar\))Tj,此方法将按Foo(bar)预期返回。这种方法会从原始pdf内容中剔除很多其他信息,例如位置坐标。


1
您是对的,在iText中出现5.xx文本提取只是作为概念验证,而在iTextSharp中根本没有。就是说,您提供的代码仅适用于非常原始的PDF(使用带有ASCII码编码的字体和Tj作为唯一的文本绘制运算符)。它可能在受严格控制的环境(您可以确保仅获取此类原始PDF)中可用,但通常不可用。
mkl 2014年

正确的Regex表达式是:(?<=()(。*?)(?=)Tj)
Diego

6

这是一个基于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(已下载)。和你一样吗?
卡特梅德林

.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文档中的任何格式,但是,我很高兴它确实保留了回车符。就我而言,文本中有足够的常量,因此我能够提取所需的值。


0

这是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();

-1
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.