2010-03-31 137 views

Respuesta

17

No puede leer y analizar el contenido de un PDF utilizando iTextSharp como le gustaría.

De iTextSharp de SourceForge tutorial:

Puede no 'de análisis' un archivo PDF existente usando iText, sólo se puede 'leer' que página por página.

¿Qué significa esto?

El formato pdf es solo un lienzo donde texto y gráficos se colocan sin información de estructura. Como tal no hay ningún 'iText-objects' en un archivo PDF . En cada página habrá , probablemente sea un número de 'Cadenas', pero no puede reconstruir una frase o un párrafo usando estas cadenas. Hay es probable que haya varias líneas dibujadas, pero no se puede recuperar un objeto de tabla según estas líneas. En resumen: el análisis del contenido de un archivo PDF es NO ES POSIBLE con iText. Publique una pregunta en el grupo de noticias noticia: //comp.text.pdf y tal vez obtendrá algunas respuestas de la gente que han construido herramientas que pueden analizar PDF y extraer algunos de sus contenidos, pero no esperan herramientas que realizarán una conversión a prueba de balas al texto estructurado .

+3

+1 Gracias por el extracto del tutorial. Es la única explicación más informativa (revelación, realmente) que he visto sobre los archivos PDF. Antes de leerlo, solía pensar que había algún tipo de estructura tipo Word en los archivos PDF. – Sabuncu

+0

@Sabuncu ¡Me alegro de poder ayudar! –

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

¡Esto debe marcarse como la solución! Esto funciona genial para mí –

+0

De acuerdo, esto funciona, márcalo como la respuesta. – skimania

+0

Funciona perfectamente, ¡muchas gracias! – JoseMarmolejos

6

Aquí es una solución VB.NET basado en la solución de ShravankumarKumar.

Esto SÓLO le proporcionará el texto. Las imágenes son una historia diferente.

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

Cuando intento esto en mi PDF, me da el mensaje de error "El valor no puede ser nulo. Nombre del parámetro: valor". ¿Alguna idea de qué se trata esto? – Avi

+0

¿Puede decirme qué línea de código le da ese error? –

+0

sOut & = iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage (oReader, i, its). Además, descubrí algo acerca de este error. Si lo saco del ciclo y analizo las páginas individuales, funciona en una página y no en la otra. La única diferencia entre los dos que puedo decir es que la página problemática tiene imágenes (que no necesito). – 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); 

Ninguna de las otras respuestas fueron útiles para mí, todos ellos parecen apuntar a la v5 AGPL de iTextSharp. Nunca pude encontrar ninguna referencia a SimpleTextExtractionStrategy o LocationTextExtractionStrategy en la versión de FOSS.

Otra cosa que podría ser muy útil en conjunción con esto:

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

Esto extraerá el texto sólo los datos de la PDF, si el texto que se muestra es Foo(bar) que se codifica en el PDF como (Foo\(bar\))Tj, este método devolvería Foo(bar) como se esperaba. Este método eliminará mucha información adicional, como las coordenadas de ubicación del contenido pdf en bruto.

+1

Tiene razón, antes de la extracción de texto 5.x.x estaba presente en iText simplemente como prueba de concepto y en iTextSharp en absoluto. Dicho esto, el código que presenta solo funciona en archivos PDF muy primitivos (utilizando fuentes con una codificación ASCII'ish y ** Tj ** como único operador de dibujo de texto). Puede usarse en entornos muy controlados (en los que puede asegurarse de obtener solo archivos PDF primitivos) pero no en general. – mkl

4

En mi caso, solo quería el texto de un área específica del documento PDF, así que usé un rectángulo alrededor del área y extraje el texto del mismo. En el ejemplo a continuación, las coordenadas son para toda la página.No tengo herramientas de creación de PDF, así que cuando llegó el momento de reducir el rectángulo a la ubicación específica, hice algunas conjeturas sobre las coordenadas hasta que se encontró el área.

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

Como se ha señalado por los comentarios sobre el texto resultante no mantiene ninguna parte del formato que se encuentra en el documento PDF, sin embargo, estaba contento de que lo hizo preservar los retornos de carro. En mi caso, había suficientes constantes en el texto que pude extraer los valores que necesitaba.

Cuestiones relacionadas