Lesen von PDF-Inhalten mit der itextsharp-DLL in VB.NET oder C #


80

Wie kann ich PDF-Inhalte mit dem itextsharp mit der Pdfreader-Klasse lesen? Mein PDF kann einfachen Text oder Bilder des Textes enthalten.


iTextSharp heißt jetzt "iText 7 für .NET" oder "itext7-dotnet" auf github: link . Es wird empfohlen, itext7 mit Nuget zu Ihrer Lösung hinzuzufügen.
Peter Huber

Antworten:


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
Dies sollte als Lösung markiert werden! Das funktioniert gut für mich.
Carter Medlin

1
Ein bestimmter Grund der pdfReader.Close (); passiert innerhalb der for-Schleife?
Do 00 mÄ

8
warum überhaupt .Close () verwenden und nichtusing (var pdfReader = ...) {}
Sebastian

2
Auch ASCIIEncoding.Convertsollte Encoding.Convertes eine statische Methode sein
Sebastian

Wenn jemand einen ähnlichen Code wie oben benötigt, Schritt für Schritt implementiert, um den PDF-Text in C # zu lesen, finden Sie hier den Link: qawithexperts.com/article/c-sharp/… danke
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);

Keine der anderen Antworten war für mich nützlich, sie scheinen alle auf die AGPL v5 von iTextSharp abzuzielen. Ich konnte nie einen Hinweis auf SimpleTextExtractionStrategyoder LocationTextExtractionStrategyin der FOSS-Version finden.

Etwas anderes, das in Verbindung damit sehr nützlich sein könnte:

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

Dadurch werden die Nur-Text-Daten aus der PDF-Datei extrahiert, wenn der angezeigte Text Foo(bar)in der PDF-Datei codiert (Foo\(bar\))Tjist. Diese Methode würde Foo(bar)wie erwartet zurückgegeben. Diese Methode entfernt viele zusätzliche Informationen wie Standortkoordinaten aus dem unformatierten PDF-Inhalt.


1
Sie haben Recht, bevor die 5.xx-Textextraktion in iText lediglich als Proof-of-Concept und in iTextSharp überhaupt nicht vorhanden war. Abgesehen davon funktioniert der von Ihnen präsentierte Code nur in sehr primitiv erstellten PDFs (unter Verwendung von Schriftarten mit ASCII'ish-Codierung und Tj als einzigem Textzeichnungsoperator). Es kann in sehr kontrollierten Umgebungen verwendet werden (in denen Sie sicherstellen können, dass nur solche primitiven PDFs abgerufen werden), jedoch nicht im Allgemeinen.
mkl

6

Hier ist eine VB.NET-Lösung, die auf der Lösung von ShravankumarKumar basiert.

Dies gibt Ihnen NUR den Text. Die Bilder sind eine andere Geschichte.

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

Wenn ich dies in meiner PDF-Datei versuche, wird die Fehlermeldung "Wert kann nicht null sein. Parametername: Wert" angezeigt. Irgendeine Idee, worum es geht?
Avi

sOut & = iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage (oReader, i, its). Außerdem habe ich etwas über diesen Fehler herausgefunden. Wenn ich es aus der Schleife nehme und die einzelnen Seiten analysiere, funktioniert es auf einer Seite und nicht auf der anderen. Der einzige Unterschied zwischen den beiden, den ich feststellen kann, ist, dass die problematische Seite Bilder enthält (die ich nicht brauche).
Avi

Wenn Sie sich das PDF ansehen möchten, kann ich es Ihnen senden.
Avi

Ich verwende .Net 4.0 und itextsharp 5.1.2.0 (gerade heruntergeladen). Dir ebenfalls?
Carter Medlin

.Net 3.5 und itextsharp 5.1.1. Ich werde aktualisieren und sehen, ob es behoben ist.
Avi

5

In meinem Fall wollte ich nur den Text aus einem bestimmten Bereich des PDF-Dokuments, also habe ich ein Rechteck um den Bereich verwendet und den Text daraus extrahiert. Im folgenden Beispiel beziehen sich die Koordinaten auf die gesamte Seite. Ich habe keine PDF-Authoring-Tools. Als es darum ging, das Rechteck auf den bestimmten Ort einzugrenzen, habe ich einige Vermutungen an den Koordinaten angestellt, bis der Bereich gefunden wurde.

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

Wie aus den obigen Kommentaren hervorgeht, behält der resultierende Text keine der im PDF-Dokument gefundenen Formatierungen bei. Ich war jedoch froh, dass die Wagenrückläufe beibehalten wurden. In meinem Fall enthielt der Text genügend Konstanten, um die erforderlichen Werte zu extrahieren.


0

Hier eine verbesserte Antwort von ShravankumarKumar. Ich habe spezielle Klassen für die Seiten erstellt, damit Sie basierend auf den Textzeilen und dem Wort in dieser Zeile auf Wörter im PDF zugreifen können.

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

Die benutzerdefinierten Klassen

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

Jetzt können Sie ein Wort nach Zeile und Wortindex erhalten.

string myWord = pages[0].rows[12].words[4];

Oder verwenden Sie Linq, um die Zeilen zu finden, die ein bestimmtes Wort enthalten.

//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
Die Frage lautet, eine PDF-Datei zu lesen. Ihre Antwort erstellt eine!
AaA
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.