2010-03-31 13 views

risposta

17

Non è possibile leggere e analizzare il contenuto di un PDF utilizzando iTextSharp come si desidera.

Da iTextSharp di SourceForge tutorial:

non si puo 'analizzare' un file PDF esistente usando iText, si può solo 'leggere' si pagina per pagina.

Cosa significa?

Il formato pdf è solo una tela in cui il testo e la grafica sono posizionati senza qualsiasi informazione di struttura. Come tale non ci sono "oggetti iText" in un file PDF . In ogni pagina ci sarà probabilmente un numero di 'Stringhe', ma non è possibile ricostruire una frase o un paragrafo usando queste stringhe. Lì sono probabilmente un numero di linee tracciate, ma non è possibile recuperare un oggetto tabella in base a queste righe. In breve: l'analisi del contenuto di un file PDF è NON POSSIBILE con iText. Pubblica la tua domanda sul newsgroup notizia: //comp.text.pdf e forse otterrete alcune risposte da parte di persone che hanno costruito strumenti in grado di analizzare PDF ed estrarre alcuni dei suoi contenuti, ma non aspettatevi strumenti che eseguiranno una conversione a prova di proiettile in testo strutturato .

+3

+1 Grazie per l'estratto del tutorial. È l'unica spiegazione più informativa (rivelazione, davvero) che abbia mai visto sui file PDF. Prima di leggerlo, ero solito pensare che all'interno dei file PDF esistesse una sorta di struttura simile a Word. – Sabuncu

+0

@Sabuncu Felice di essere in grado di aiutare! –

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

Questo dovrebbe essere contrassegnato come la soluzione! Questo funziona alla grande per me. –

+0

D'accordo, funziona, segnalo come risposta. – skimania

+0

Funziona perfettamente, grazie mille! – JoseMarmolejos

6

Ecco una soluzione basata su VB.NET soluzione ShravankumarKumar.

Questo vi darà SOLO il testo. Le immagini sono una storia diversa.

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 
+0

Quando provo questo sul mio PDF, mi dà il messaggio di errore, "Il valore non può essere nullo. Nome del parametro: valore". Qualche idea di cosa si tratta? – Avi

+0

Puoi dirmi quale riga di codice ti dà quell'errore? –

+0

sOut & = iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage (oReader, i, its). Inoltre, ho capito qualcosa su questo errore. Se tendo fuori dal giro e analizzo le singole pagine, funziona su una pagina e non sull'altra. L'unica differenza tra i due che posso dire è che la pagina problematica contiene delle immagini (di cui non ho bisogno). – Avi

0
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 
10

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

Nessuna delle altre risposte erano utili per me, tutti sembrano indirizzare la v5 AGPL di iTextSharp. Non ho mai trovato alcun riferimento a SimpleTextExtractionStrategy o LocationTextExtractionStrategy nella versione FOSS.

Un'altra cosa che potrebbe essere molto utile in concomitanza con questo:

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

Ciò estrarre il testo solo i dati dal PDF, se il testo visualizzato è Foo(bar) sarà codificato nel PDF come (Foo\(bar\))Tj, questo metodo restituirebbe Foo(bar) come previsto. Questo metodo eliminerà molte informazioni aggiuntive come le coordinate della posizione dal contenuto PDF grezzo.

+1

Hai ragione, prima che l'estrazione del testo 5.x.x fosse presente in iText semplicemente come proof-of-concept e in iTextSharp non lo fosse affatto. Detto questo, il codice che si presenta funziona solo in PDF molto primitivi (usando i caratteri con una codifica ASCII e ** Tj ** come solo operatore di disegno di testo). Può essere utilizzabile in ambienti molto controllati (in cui è possibile assicurarsi di ottenere solo PDF così primitivi) ma non in generale. – mkl

4

Nel mio caso volevo solo il testo da un'area specifica del documento PDF, così ho usato un rettangolo intorno all'area e ho estratto il testo da esso. Nell'esempio sotto le coordinate sono per l'intera pagina.Non ho strumenti per la creazione di PDF, quindi quando è arrivato il momento di restringere il rettangolo alla posizione specifica, ho preso alcune ipotesi sulle coordinate fino a quando l'area non è stata trovata.

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

Come notato dai commenti sopra il testo risultante non mantiene nessuno degli formattazione trovata nel documento PDF, ma ero felice che lo ha fatto preservare i ritorni a capo. Nel mio caso c'erano abbastanza costanti nel testo che sono stato in grado di estrarre i valori che ho richiesto.