PDF-Dokumente in .Net lesen [geschlossen]

88

Gibt es eine Open Source-Bibliothek, die mir beim Lesen / Parsen von PDF-Dokumenten in .Net / C # hilft?

JRoppert
quelle
1
Die Antwort von Brock Nusser
scheint die
Weitere aktualisierte iTextSharp-Antworten finden Sie hier, da diese Frage geschlossen ist.
VDWWD

Antworten:

115

Seit diese Frage 2008 das letzte Mal beantwortet wurde, hat iTextSharp seine API dramatisch verbessert. Wenn Sie die neueste Version ihrer API von http://sourceforge.net/projects/itextsharp/ herunterladen , können Sie den folgenden Textausschnitt verwenden, um den gesamten Text aus einem PDF in eine Zeichenfolge zu extrahieren.

using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

namespace PdfParser
{
    public static class PdfTextExtractor
    {
        public static string pdfText(string path)
        {
            PdfReader reader = new PdfReader(path);
            string text = string.Empty;
            for(int page = 1; page <= reader.NumberOfPages; page++)
            {
                text += PdfTextExtractor.GetTextFromPage(reader,page);
            }
            reader.Close();
            return text;
        }   
    }
}
Brock Nusser
quelle
17
Sie sollten Ihre Klasse wahrscheinlich nicht anrufen, PdfTextExtractorda sie mit der iniTextSharp.text.pdf.parser
Neil
2
iTextSharp ist zu GitHub umgezogen: github.com/itext/itextsharp
Amedee Van Gasse
1
vielleicht diejenigen , die hier beantwortet könnten helfen hier ?
Veverke
6
Es wird jetzt für kommerzielle Projekte bezahlt.
Nikolay Kostov
1
@iTextSharp ist veraltet und wurde durch iText 7 github.com/itext/itext7-dotnet ersetzt .
Matthew
62

iTextSharp ist die beste Wahl . Verwendet es, um eine Spinne für Lucene.Net zu erstellen, damit es PDF crawlen kann.

using System;
using System.IO;
using iTextSharp.text.pdf;
using System.Text.RegularExpressions;

namespace Spider.Utils
{
    /// <summary>
    /// Parses a PDF file and extracts the text from it.
    /// </summary>
    public class PDFParser
    {
        /// BT = Beginning of a text object operator 
        /// ET = End of a text object operator
        /// Td move to the start of next line
        ///  5 Ts = superscript
        /// -5 Ts = subscript

        #region Fields

        #region _numberOfCharsToKeep
        /// <summary>
        /// The number of characters to keep, when extracting text.
        /// </summary>
        private static int _numberOfCharsToKeep = 15;
        #endregion

        #endregion

        #region ExtractText
        /// <summary>
        /// Extracts a text from a PDF file.
        /// </summary>
        /// <param name="inFileName">the full path to the pdf file.</param>
        /// <param name="outFileName">the output file name.</param>
        /// <returns>the extracted text</returns>
        public bool ExtractText(string inFileName, string outFileName)
        {
            StreamWriter outFile = null;
            try
            {
                // Create a reader for the given PDF file
                PdfReader reader = new PdfReader(inFileName);
                //outFile = File.CreateText(outFileName);
                outFile = new StreamWriter(outFileName, false, System.Text.Encoding.UTF8);

                Console.Write("Processing: ");

                int totalLen = 68;
                float charUnit = ((float)totalLen) / (float)reader.NumberOfPages;
                int totalWritten = 0;
                float curUnit = 0;

                for (int page = 1; page <= reader.NumberOfPages; page++)
                {
                    outFile.Write(ExtractTextFromPDFBytes(reader.GetPageContent(page)) + " ");

                    // Write the progress.
                    if (charUnit >= 1.0f)
                    {
                        for (int i = 0; i < (int)charUnit; i++)
                        {
                            Console.Write("#");
                            totalWritten++;
                        }
                    }
                    else
                    {
                        curUnit += charUnit;
                        if (curUnit >= 1.0f)
                        {
                            for (int i = 0; i < (int)curUnit; i++)
                            {
                                Console.Write("#");
                                totalWritten++;
                            }
                            curUnit = 0;
                        }

                    }
                }

                if (totalWritten < totalLen)
                {
                    for (int i = 0; i < (totalLen - totalWritten); i++)
                    {
                        Console.Write("#");
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                if (outFile != null) outFile.Close();
            }
        }
        #endregion

        #region ExtractTextFromPDFBytes
        /// <summary>
        /// This method processes an uncompressed Adobe (text) object 
        /// and extracts text.
        /// </summary>
        /// <param name="input">uncompressed</param>
        /// <returns></returns>
        public string ExtractTextFromPDFBytes(byte[] input)
        {
            if (input == null || input.Length == 0) return "";

            try
            {
                string resultString = "";

                // Flag showing if we are we currently inside a text object
                bool inTextObject = false;

                // Flag showing if the next character is literal 
                // e.g. '\\' to get a '\' character or '\(' to get '('
                bool nextLiteral = false;

                // () Bracket nesting level. Text appears inside ()
                int bracketDepth = 0;

                // Keep previous chars to get extract numbers etc.:
                char[] previousCharacters = new char[_numberOfCharsToKeep];
                for (int j = 0; j < _numberOfCharsToKeep; j++) previousCharacters[j] = ' ';


                for (int i = 0; i < input.Length; i++)
                {
                    char c = (char)input[i];
                    if (input[i] == 213)
                        c = "'".ToCharArray()[0];

                    if (inTextObject)
                    {
                        // Position the text
                        if (bracketDepth == 0)
                        {
                            if (CheckToken(new string[] { "TD", "Td" }, previousCharacters))
                            {
                                resultString += "\n\r";
                            }
                            else
                            {
                                if (CheckToken(new string[] { "'", "T*", "\"" }, previousCharacters))
                                {
                                    resultString += "\n";
                                }
                                else
                                {
                                    if (CheckToken(new string[] { "Tj" }, previousCharacters))
                                    {
                                        resultString += " ";
                                    }
                                }
                            }
                        }

                        // End of a text object, also go to a new line.
                        if (bracketDepth == 0 &&
                            CheckToken(new string[] { "ET" }, previousCharacters))
                        {

                            inTextObject = false;
                            resultString += " ";
                        }
                        else
                        {
                            // Start outputting text
                            if ((c == '(') && (bracketDepth == 0) && (!nextLiteral))
                            {
                                bracketDepth = 1;
                            }
                            else
                            {
                                // Stop outputting text
                                if ((c == ')') && (bracketDepth == 1) && (!nextLiteral))
                                {
                                    bracketDepth = 0;
                                }
                                else
                                {
                                    // Just a normal text character:
                                    if (bracketDepth == 1)
                                    {
                                        // Only print out next character no matter what. 
                                        // Do not interpret.
                                        if (c == '\\' && !nextLiteral)
                                        {
                                            resultString += c.ToString();
                                            nextLiteral = true;
                                        }
                                        else
                                        {
                                            if (((c >= ' ') && (c <= '~')) ||
                                                ((c >= 128) && (c < 255)))
                                            {
                                                resultString += c.ToString();
                                            }

                                            nextLiteral = false;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Store the recent characters for 
                    // when we have to go back for a checking
                    for (int j = 0; j < _numberOfCharsToKeep - 1; j++)
                    {
                        previousCharacters[j] = previousCharacters[j + 1];
                    }
                    previousCharacters[_numberOfCharsToKeep - 1] = c;

                    // Start of a text object
                    if (!inTextObject && CheckToken(new string[] { "BT" }, previousCharacters))
                    {
                        inTextObject = true;
                    }
                }

                return CleanupContent(resultString);
            }
            catch
            {
                return "";
            }
        }

        private string CleanupContent(string text)
        {
            string[] patterns = { @"\\\(", @"\\\)", @"\\226", @"\\222", @"\\223", @"\\224", @"\\340", @"\\342", @"\\344", @"\\300", @"\\302", @"\\304", @"\\351", @"\\350", @"\\352", @"\\353", @"\\311", @"\\310", @"\\312", @"\\313", @"\\362", @"\\364", @"\\366", @"\\322", @"\\324", @"\\326", @"\\354", @"\\356", @"\\357", @"\\314", @"\\316", @"\\317", @"\\347", @"\\307", @"\\371", @"\\373", @"\\374", @"\\331", @"\\333", @"\\334", @"\\256", @"\\231", @"\\253", @"\\273", @"\\251", @"\\221"};
            string[] replace = {   "(",     ")",      "-",     "'",      "\"",      "\"",    "à",      "â",      "ä",      "À",      "Â",      "Ä",      "é",      "è",      "ê",      "ë",      "É",      "È",      "Ê",      "Ë",      "ò",      "ô",      "ö",      "Ò",      "Ô",      "Ö",      "ì",      "î",      "ï",      "Ì",      "Î",      "Ï",      "ç",      "Ç",      "ù",      "û",      "ü",      "Ù",      "Û",      "Ü",      "®",      "™",      "«",      "»",      "©",      "'" };

            for (int i = 0; i < patterns.Length; i++)
            {
                string regExPattern = patterns[i];
                Regex regex = new Regex(regExPattern, RegexOptions.IgnoreCase);
                text = regex.Replace(text, replace[i]);
            }

            return text;
        }

        #endregion

        #region CheckToken
        /// <summary>
        /// Check if a certain 2 character token just came along (e.g. BT)
        /// </summary>
        /// <param name="tokens">the searched token</param>
        /// <param name="recent">the recent character array</param>
        /// <returns></returns>
        private bool CheckToken(string[] tokens, char[] recent)
        {
            foreach (string token in tokens)
            {
                if ((recent[_numberOfCharsToKeep - 3] == token[0]) &&
                    (recent[_numberOfCharsToKeep - 2] == token[1]) &&
                    ((recent[_numberOfCharsToKeep - 1] == ' ') ||
                    (recent[_numberOfCharsToKeep - 1] == 0x0d) ||
                    (recent[_numberOfCharsToKeep - 1] == 0x0a)) &&
                    ((recent[_numberOfCharsToKeep - 4] == ' ') ||
                    (recent[_numberOfCharsToKeep - 4] == 0x0d) ||
                    (recent[_numberOfCharsToKeep - 4] == 0x0a))
                    )
                {
                    return true;
                }
            }
            return false;
        }
        #endregion
    }
}
Ceetheman
quelle
1
hallo ceetheman, ich habe versucht, den oben angegebenen code zu verwenden ... aber ein problem bekommen. Einige meiner PDF-Dateien werden richtig gelesen, aber in einigen PDF-Dateien habe ich den Fehler "Index außerhalb des Bereichs" in der Funktion "CheckToken" erhalten. Können Sie mir bitte helfen, dieses Problem zu lösen?
Radhi
18
Es ist eine gute und höfliche Idee, auf die Quelle Ihres Beispiels zu verweisen. In diesem Fall finden Sie den gleichen Quellcode hier codeproject.com/KB/cs/PDFToText.aspx
Myster
2
Ich habe Probleme mit diesem Code, er gibt ein Gobledegook zurück, das aus den Buchstaben r und n besteht. Am Ende habe ich PDFBox verwendet.
Myster
So seltsam ... Ich habe mein PDF eingesteckt und 1627 leere Zeilen in meiner Textdatei ...
Ortund
1
Die Antwort von Brock Nusser scheint die aktuellste Lösung zu sein und sollte als die richtige Antwort auf diese Frage angesehen werden.
Ceetheman
6
public string ReadPdfFile(object Filename, DataTable ReadLibray)
{
    PdfReader reader2 = new PdfReader((string)Filename);
    string strText = string.Empty;

    for (int page = 1; page <= reader2.NumberOfPages; page++)
    {
    ITextExtractionStrategy its = new iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy();
    PdfReader reader = new PdfReader((string)Filename);
    String s = PdfTextExtractor.GetTextFromPage(reader, page, its);

    s = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(s)));
    strText = strText + s;
    reader.Close();
    }
    return strText;
}
ShravankumarKumar
quelle
1
Die einzige Methode, die bei mir funktioniert hat! Danke Alter!
Briba
PDF Reader? Bitte fügen Sie einige Informationen hinzu.
DxTx
1
@DT siehe iTextSharp
dontbyteme
6

PDFClown könnte helfen, aber ich würde es nicht für eine große oder stark genutzte Anwendung empfehlen.

Ilya Kochetov
quelle
Lizenzierte LGPL, damit damit kommerzielle, proprietäre Software erstellt werden kann.
Sylwester Santorowski
3

iText ist die beste Bibliothek, die ich kenne. Ursprünglich in Java geschrieben, gibt es auch einen .NET-Port.

Siehe http://www.ujihara.jp/iTextdotNET/en/


quelle
Das ist kein offizieller Port und die Verbindung ist sowieso unterbrochen. Der offizielle .NET-Port von iText, iTextSharp, ist auf GitHub zu finden: github.com/itext/itextsharp
Amedee Van Gasse
1

Sie könnten dies prüfen : http://www.codeproject.com/KB/showcase/pdfrasterizer.aspx Es ist nicht ganz kostenlos, aber es sieht sehr gut aus.

Alex

Alex Fort
quelle
1
Kann dies helfen, PDF in Rohtext zu konvertieren? Scheint, dass das Werkzeug es in ein Bild konvertiert. Also brauche ich dann eine OCR-Bibliothek :-)
JRoppert
1

aspose pdf funktioniert ziemlich gut. Andererseits muss man dafür bezahlen

Kuvo
quelle
0

Es gibt auch LibHaru

http://libharu.org/wiki/Main_Page

Cetra
quelle
Verbindung unterbrochen. libharu.org
TernaryTopiary
1
Außerdem: "Derzeit unterstützt libHaru das Lesen und Bearbeiten vorhandener PDF-Dateien nicht und es ist unwahrscheinlich, dass diese Unterstützung jemals angezeigt wird." Ist das tatsächlich relevant?
TernaryTopiary
0

Schauen Sie sich die Docotic.Pdf-Bibliothek an . Sie müssen den Quellcode Ihrer Anwendung nicht öffnen (z. B. iTextSharp mit viraler AGPL 3-Lizenz).

Docotic.Pdf kann zum Lesen von PDF-Dateien und zum Extrahieren von Text mit oder ohne Formatierung verwendet werden. Bitte lesen Sie den Artikel, der zeigt, wie Sie Text aus PDFs extrahieren .

Haftungsausschluss: Ich arbeite für Bit Miracle, den Anbieter der Bibliothek.

Bobrovsky
quelle
4
Nur 30 Tage frei. Keine gute Option ...
José Augustinho