繁体   English   中英

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

[英]Reading PDF content with itextsharp dll in VB.NET or C#

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

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

您无法按照自己的意愿使用iTextSharp读取和解析PDF的内容。

从iTextSharp的SourceForge教程中

您无法使用iText来“解析”现有的PDF文件,而只能每页“读取”它。

这是什么意思?

pdf格式只是一个放置文本和图形的画布,没有任何结构信息。 因此,PDF文件中没有任何“ iText对象”。 每个页面中可能会有许多“字符串”,但是您无法使用这些字符串来重建短语或段落。 可能会画出许多线,但是您不能基于这些线来检索Table对象。 简而言之:使用iText解析PDF文件的内容是不可能的。 将您的问题发布到新闻组news://comp.text.pdf上,也许您会从那些已经构建了可以解析PDF并提取其某些内容的工具的人那里得到一些答案,但是不要指望能够执行项目符号的工具转换为结构化文本。

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 版本中找不到任何对SimpleTextExtractionStrategyLocationTextExtractionStrategy引用。

与此结合可能非常有用的其他内容:

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 内容中去除大量附加信息,例如位置坐标。

这是一个基于 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 文档特定区域中的文本,因此我在该区域周围使用了一个矩形并从中提取了文本。 在下面的示例中,坐标用于整个页面。 我没有 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 文档中的任何格式,但是,我很高兴它确实保留了回车符。 就我而言,文本中有足够的常量,我能够提取所需的值。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM