2008-09-17 3 views
62

Есть ли библиотека с открытым исходным кодом, которая помогает мне читать/разбирать документы PDF в .Net/C#?Чтение PDF-документов в .Net

+0

Ответ предоставляется Брок Nusser выглядит наиболее решение уточненный и должны рассматриваться как правильный ответ на этот вопрос – ceetheman 2018-01-11 15:38:47

ответ

50

iTextSharp - лучший выбор. Использовал его, чтобы сделать паук для lucene.Net, чтобы он мог сканировать PDF.

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 
    } 
} 
+1

Привет, я пробовал использовать код, который вы указали выше ... , но возникает одна проблема. мои некоторые pdf-файлы читаются правильно, но в каком-то файле pdf я получил ошибку «Index Out of Range» в функции «CheckToken». не могли бы вы помочь мне решить эту проблему? – Radhi 2010-02-22 12:38:58

+12

Ссылка на источник вашего примера - хорошая и вежливая идея. В этом случае тот же исходный код можно найти здесь http://www.codeproject.com/KB/cs/PDFToText.aspx – Myster 2010-04-29 00:22:33

1

Вы можете посмотреть на это: http://www.codeproject.com/KB/showcase/pdfrasterizer.aspx Это не совсем бесплатный, но выглядит очень красиво.

Alex

+1

Может ли эта помощь конвертировать PDF в исходный текст? Кажется, этот инструмент преобразует его в изображение. Так что мне нужна библиотека OCR, тогда :-) – JRoppert 2008-09-17 13:33:42

4

PDFClown может помочь, но я бы не рекомендовал его для большого или тяжелого применения использования.

+0

очень хорошее решение – Evgeny 2011-02-11 10:18:52

1

Существует также LibHaru

http://libharu.org/wiki/Main_Page

+0

Ссылка сломана. Http: // libharu.org/ – TernaryTopiary 2017-05-08 06:37:18

+1

Также: «В настоящий момент libHaru не поддерживает чтение и редактирование существующих файлов PDF, и вряд ли эта поддержка когда-либо появится». Это действительно актуально? – TernaryTopiary 2017-05-08 06:38:01

3

IText это лучшая библиотека я знаю. Первоначально написанный на Java, есть и порт .NET.

См http://www.ujihara.jp/iTextdotNET/en/

+0

Это не официальный порт, и ссылка все равно сломана. Официальный .NET-порт iText, iTextSharp, можно найти на GitHub: http://github.com/itext/itextsharp – 2015-12-09 15:39:55

4

В прошлом я использовал ITextSharp, чтобы манипулировать/разделять и редактировать документы PDF - это довольно просто, а также с открытым исходным кодом.

2

aspose pdf работает очень хорошо. то за это вам необходимо заплатить

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

С последнего эта последнего вопроса в 2008 году iTextSharp значительно улучшил свои возможности. Если вы загрузите последнюю версию своего api с http://sourceforge.net/projects/itextsharp/, вы можете использовать следующий фрагмент кода, чтобы извлечь весь текст из pdf в строку.

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

Посмотрите на Docotic.Pdf library. Это не требует, чтобы вы открывали исходный код вашего приложения (например, iTextSharp с вирусной лицензией AGPL 3).

Docotic.Pdf может использоваться для чтения PDF-файлов и извлечения текста с форматированием или без него. Пожалуйста, посмотрите образец, который показывает how to extract text from PDFs.

Отказ от ответственности: Я работаю над Bit Miracle, продавцом библиотеки.

Смежные вопросы