2014-10-30 3 views
3

По folowing сообщение: iTextSharp PDF Reading highlighed text (highlight annotations) using C#Как извлечь текст из PDF с помощью iTextSharp?

этот код:

for (int i = pageFrom; i <= pageTo; i++) { 
    PdfDictionary page = reader.GetPageN(i); 
    PdfArray annots = page.GetAsArray(iTextSharp.text.pdf.PdfName.ANNOTS); 
    if (annots!=null) 
     foreach (PdfObject annot in annots.ArrayList) { 
      PdfDictionary annotation = (PdfDictionary)PdfReader.GetPdfObject(annot); 
      PdfString contents = annotation.GetAsString(PdfName.CONTENTS); 
      // now use the String value of contents 
     } 
    } 
} 

работает, чтобы извлечь PDF аннотаций. Но почему же следующий код не работает для подсветки (в частности PdfName.HIGHLIGHT не работает):

for (int i = pageFrom; i <= pageTo; i++) { 
    PdfDictionary page = reader.GetPageN(i); 
    PdfArray annots = page.GetAsArray(iTextSharp.text.pdf.PdfName.HIGHLIGHT); 
    if (annots!=null) 
     foreach (PdfObject annot in annots.ArrayList) { 
      PdfDictionary annotation = (PdfDictionary)PdfReader.GetPdfObject(annot); 
      PdfString contents = annotation.GetAsString(PdfName.CONTENTS); 
      // now use the String value of contents 
     } 
    } 
} 

ответ

3

Пожалуйста, обратите внимание на таблицу 30 в ISO-32000-1 (ака ссылки PDF). Он называется «Записи в объекте страницы». Среди этих записей вы можете найти ключ с именем Annots. Его значение:

(Необязательно) Массив аннотаций словарей, которые должны содержать косвенные ссылки на все аннотации, связанные со страницей (см 12,5, «Аннотации»).

Вы не найдете запись с ключом, такие как Highlight, следовательно, это нормально, что массив, который возвращается равно нулю, когда у вас есть эта строка:

PdfArray annots = page.GetAsArray(iTextSharp.text.pdf.PdfName.HIGHLIGHT); 

Вы должны получить аннотации, как вы уже сделали:

PdfArray annots = page.GetAsArray(iTextSharp.text.pdf.PdfName.ANNOTS); 

Теперь вам нужна цикл по этому массиву и искать аннотации с Subtype равным Highlight. Этот тип аннотации приведен в таблице 169 ISO-32000-1, озаглавленной «Типы аннотаций».

Другими словами, ваше предположение о том, что словарь страниц содержит записи с ключом Highlight, является неправильным, и если вы прочитаете всю спецификацию, вы также обнаружите другое ложное предположение, которое вы делали. Вы ошибочно полагаете, что выделенный текст сохраняется в записи аннотаций Contents. Это показывает отсутствие понимания природы аннотаций и содержания страницы.

Текст, который вы ищите, хранится в потоке содержимого страницы. Поток содержимого страницы не зависит от аннотаций страницы. Следовательно, чтобы получить выделенный текст, вам нужно получить координаты, хранящиеся в аннотации Highlight (хранящейся в массиве QuadPoints), и вам нужно использовать эти координаты для анализа текста, который присутствует в содержимом страницы в этих координатах.

2

Вот полный пример извлечения выделенного текста с помощью itextSharp

public void GetRectAnno() 
    { 

     string appRootDir = new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.FullName; 

     string filePath = appRootDir + "/PDFs/" + "anot.pdf"; 

     int pageFrom = 0; 
     int pageTo = 0; 

     try 
     { 
      using (PdfReader reader = new PdfReader(filePath)) 
      { 
       pageTo = reader.NumberOfPages; 

       for (int i = 1; i <= reader.NumberOfPages; i++) 
       { 


        PdfDictionary page = reader.GetPageN(i); 
        PdfArray annots = page.GetAsArray(iTextSharp.text.pdf.PdfName.ANNOTS); 
        if (annots != null) 
         foreach (PdfObject annot in annots.ArrayList) 
         { 

          //Get Annotation from PDF File 
          PdfDictionary annotationDic = (PdfDictionary)PdfReader.GetPdfObject(annot); 
          PdfName subType = (PdfName)annotationDic.Get(PdfName.SUBTYPE); 
          //check only subtype is highlight 
          if (subType.Equals(PdfName.HIGHLIGHT)) 
          { 
           // Get Quadpoints and Rectangle of highlighted text 
           Console.Write("HighLight at Rectangle {0} with QuadPoints {1}\n", annotationDic.GetAsArray(PdfName.RECT), annotationDic.GetAsArray(PdfName.QUADPOINTS)); 

           //Extract Text using rectangle strategy  
           PdfArray coordinates = annotationDic.GetAsArray(PdfName.RECT); 

           Rectangle rect = new Rectangle(float.Parse(coordinates.ArrayList[0].ToString(), CultureInfo.InvariantCulture.NumberFormat), float.Parse(coordinates.ArrayList[1].ToString(), CultureInfo.InvariantCulture.NumberFormat), 
           float.Parse(coordinates.ArrayList[2].ToString(), CultureInfo.InvariantCulture.NumberFormat),float.Parse(coordinates.ArrayList[3].ToString(), CultureInfo.InvariantCulture.NumberFormat)); 



           RenderFilter[] filter = { new RegionTextRenderFilter(rect) }; 
           ITextExtractionStrategy strategy; 
           StringBuilder sb = new StringBuilder(); 


           strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), filter); 
           sb.AppendLine(PdfTextExtractor.GetTextFromPage(reader, i, strategy)); 

           //Show extract text on Console 
           Console.WriteLine(sb.ToString()); 
           //Console.WriteLine("Page No" + i); 

          } 



         } 



       } 
      } 
     } 
     catch (Exception ex) 
     { 
     } 
    } 
+1

В случае многострочного основные моменты, которые начинаются или в конце в середине линии вы будете извлекать слишком много. Попробуйте изучить ** QuadPoints ** вместо ** Rect **. Например. [этот вопрос] (http://stackoverflow.com/q/32608083/1729265) обсуждает именно такую ​​ситуацию, хотя и для другой библиотеки, и [этот ответ] (http://stackoverflow.com/a/33278436/1729265) обсуждает детали. – mkl