Wie kann ich PDF-Inhalte mit dem itextsharp mit der Pdfreader-Klasse lesen? Mein PDF kann einfachen Text oder Bilder des Textes enthalten.
Wie kann ich PDF-Inhalte mit dem itextsharp mit der Pdfreader-Klasse lesen? Mein PDF kann einfachen Text oder Bilder des Textes enthalten.
Antworten:
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();
}
using (var pdfReader = ...) {}
ASCIIEncoding.Convert
sollte Encoding.Convert
es eine statische Methode sein
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 SimpleTextExtractionStrategy
oder LocationTextExtractionStrategy
in 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\))Tj
ist. Diese Methode würde Foo(bar)
wie erwartet zurückgegeben. Diese Methode entfernt viele zusätzliche Informationen wie Standortkoordinaten aus dem unformatierten PDF-Inhalt.
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
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.
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();
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