2011-07-30 22 views
19

Tôi đang sử dụng iTextSharp để đọc nội dung văn bản từ PDF. Tôi cũng có thể đọc được điều đó. Nhưng tôi đang mất định dạng văn bản như phông chữ, màu sắc vv Có cách nào để có được định dạng đó là tốt.làm thế nào tôi có thể nhận được định dạng văn bản với iTextSharp

Dưới đây là đoạn mã tôi đang sử dụng để văn bản chính xác -

PdfReader reader = new PdfReader("F:\\EBooks\\AspectsOfAjax.pdf"); 
textBox1.Text = ExtractTextFromPDFBytes(reader.GetPageContent(1)); 

private 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 (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) 
           { 
            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 resultString; 
    } 
    catch 
    { 
     return ""; 
    } 
} 

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

Trả lời

31

Hãy để tôi thử chỉ bạn theo một hướng khác. iTextSharp có một hệ thống trích xuất văn bản thực sự đẹp và đơn giản, xử lý một số mã thông báo cơ bản. Thật không may nó không xử lý thông tin màu sắc nhưng according to @Mark Storer it might not be too hard to implement yourself.

BEGIN EDIT

tôi bắt đầu làm việc trên thực hiện thông tin màu. Xem my blog post here để biết thêm chi tiết. (Xin lỗi cho các định dạng xấu, xếp hàng để ăn tối bây giờ.)

END EDIT

Đoạn code dưới đây kết hợp một số câu hỏi và câu trả lời ở đây bao gồm this one to get the font height (mặc dù nó không chính xác) cũng như nhau (nghĩa cho cuộc sống của tôi tôi dường như không thể tìm thấy nữa) cho thấy làm thế nào để phát hiện cho faux in đậm.

PostscriptFontName trả về một số ký tự bổ sung ở phía trước tên phông chữ, tôi nghĩ rằng nó phải làm gì khi bạn nhúng tập con phông chữ.

Dưới đây là một ứng dụng WinForms hoàn chỉnh nhắm mục tiêu iTextSharp 5.1.1.0 và trích xuất văn bản dưới dạng HTML.

Ảnh chụp màn hình của mẫu PDF

Screenshot of sample PDF

Mẫu văn bản chiết xuất dưới dạng HTML

<span style="font-family:NJNSWD+Papyrus-Regular;font-size:11.61407">Hello </span> 
<span style="font-family:NJNSWD+Papyrus-Regular-Bold;font-size:11.61407">w</span> 
<span style="font-family:NJNSWD+Papyrus-Regular-Bold;font-size:37.87201">o</span> 
<span style="font-family:NJNSWD+Papyrus-Regular-Bold;font-size:11.61407">rl</span> 
<span style="font-family:NJNSWD+Papyrus-Regular;font-size:11.61407">d </span> 
<br /> 
<span style="font-family:NJNSWD+Papyrus-Regular;font-size:11.61407">Test </span> 

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Windows.Forms; 
using iTextSharp.text.pdf.parser; 
using iTextSharp.text.pdf; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      PdfReader reader = new PdfReader(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Document.pdf")); 
      TextWithFontExtractionStategy S = new TextWithFontExtractionStategy(); 
      string F = iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(reader, 1, S); 
      Console.WriteLine(F); 

      this.Close(); 
     } 

     public class TextWithFontExtractionStategy : iTextSharp.text.pdf.parser.ITextExtractionStrategy 
     { 
      //HTML buffer 
      private StringBuilder result = new StringBuilder(); 

      //Store last used properties 
      private Vector lastBaseLine; 
      private string lastFont; 
      private float lastFontSize; 

      //http://api.itextpdf.com/itext/com/itextpdf/text/pdf/parser/TextRenderInfo.html 
      private enum TextRenderMode 
      { 
       FillText = 0, 
       StrokeText = 1, 
       FillThenStrokeText = 2, 
       Invisible = 3, 
       FillTextAndAddToPathForClipping = 4, 
       StrokeTextAndAddToPathForClipping = 5, 
       FillThenStrokeTextAndAddToPathForClipping = 6, 
       AddTextToPaddForClipping = 7 
      } 



      public void RenderText(iTextSharp.text.pdf.parser.TextRenderInfo renderInfo) 
      { 
       string curFont = renderInfo.GetFont().PostscriptFontName; 
       //Check if faux bold is used 
       if ((renderInfo.GetTextRenderMode() == (int)TextRenderMode.FillThenStrokeText)) 
       { 
        curFont += "-Bold"; 
       } 

       //This code assumes that if the baseline changes then we're on a newline 
       Vector curBaseline = renderInfo.GetBaseline().GetStartPoint(); 
       Vector topRight = renderInfo.GetAscentLine().GetEndPoint(); 
       iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(curBaseline[Vector.I1], curBaseline[Vector.I2], topRight[Vector.I1], topRight[Vector.I2]); 
       Single curFontSize = rect.Height; 

       //See if something has changed, either the baseline, the font or the font size 
       if ((this.lastBaseLine == null) || (curBaseline[Vector.I2] != lastBaseLine[Vector.I2]) || (curFontSize != lastFontSize) || (curFont != lastFont)) 
       { 
        //if we've put down at least one span tag close it 
        if ((this.lastBaseLine != null)) 
        { 
         this.result.AppendLine("</span>"); 
        } 
        //If the baseline has changed then insert a line break 
        if ((this.lastBaseLine != null) && curBaseline[Vector.I2] != lastBaseLine[Vector.I2]) 
        { 
         this.result.AppendLine("<br />"); 
        } 
        //Create an HTML tag with appropriate styles 
        this.result.AppendFormat("<span style=\"font-family:{0};font-size:{1}\">", curFont, curFontSize); 
       } 

       //Append the current text 
       this.result.Append(renderInfo.GetText()); 

       //Set currently used properties 
       this.lastBaseLine = curBaseline; 
       this.lastFontSize = curFontSize; 
       this.lastFont = curFont; 
      } 

      public string GetResultantText() 
      { 
       //If we wrote anything then we'll always have a missing closing tag so close it here 
       if (result.Length > 0) 
       { 
        result.Append("</span>"); 
       } 
       return result.ToString(); 
      } 

      //Not needed 
      public void BeginTextBlock() { } 
      public void EndTextBlock() { } 
      public void RenderImage(ImageRenderInfo renderInfo) { } 
     } 
    } 
} 
+0

Cảm ơn Chris về giải pháp có giá trị và các liên kết hữu ích của bạn. Tôi sẽ cố gắng thực hiện điều này. – IrfanRaza

+0

Cảm ơn rất nhiều Chris giải pháp của bạn đã giúp chúng tôi rất nhiều, nhưng chúng tôi bị tấn công ở một nơi, làm thế nào chúng ta có thể tìm thấy nếu văn bản là gạch dưới hay không? – Deepesh

+3

Xin chào @Deepesh, rất tiếc, thông số PDF không hỗ trợ gạch dưới ở cấp văn bản thô. Thay vào đó nó được thực hiện theo một trong hai cách, hoặc thông qua chú thích (hiếm) hoặc bằng cách vẽ một hình chữ nhật rất mỏng dưới một số văn bản (phổ biến nhất). Trong cả hai trường hợp, bạn sẽ phải tính toán vị trí của văn bản liên quan đến hình chữ nhật. Trong khi kỹ thuật có thể, tôi nghĩ rằng nó sẽ là một nhức đầu khổng lồ. Tuy nhiên, nếu tài liệu của bạn là thống nhất, bạn có thể viết một số quy tắc tùy ý. –

Các vấn đề liên quan