Нечитаемый шрифт с помощью iTextSharp PRTokeniser - PullRequest
0 голосов
/ 21 января 2011

Мне нужно выполнить низкоуровневое извлечение текста с помощью PRTokeniser

Для некоторых файлов PDF все хорошо, но для некоторых других я получаю пустые строки (или, скорее, строку, состоящую из пустых полей или пустых символов).

Все такие файлы следуют этой схеме:

endobj
7 0 obj
<</BaseFont/RDZRPI+TimesNewRoman/FontDescriptor 8 0 R/Type/Font
/FirstChar 1/LastChar 10/Widths[ 444 500 444 500 444 333 500 500 278 250]
/Encoding 11 0 R/Subtype/TrueType>>
endobj
11 0 obj
<</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
1/a/b/c/d/e/f/g/h/i/space]>>
endobj 

Каждый символ в значении строки токена не является кодом ASCII или ANSI, а является индексом массива различий.Например, если у меня есть строка типа «abc», я получу 1,2,3.Тогда iTextSharp будет понимать такие коды как коды ASCII и отображать их как пустые квадратные блоки или любой другой символ.

Поэтому мне нужно получить массив подмножеств: число 1 - это «a», число 2 - это «b»."...

Проблема в том, что массив basefont.differences имеет только пустые значения, и поэтому я не знаю, как перестроить строку.

С другой стороны, стратегия. Рендерит GetResultantTextсодержание страницы правильно, но мне нужно гораздо больше деталей, и именно поэтому я использую PRTokeniser, хотя я застрял с этой проблемой шрифта.

Есть идеи?


PDFВсе потоки выглядят так:

/FirstChar 1/LastChar 8/Widths[ 722 444 278 500 250 944 333 500]
/Encoding 11 0 R/Subtype/TrueType>>
endobj
11 0 obj
<</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
1/H/e/l/o/space/W/r/d]>>

В этом случае в PDF есть только это предложение: Hellow Word.Поэтому массив chars будет:

1 H
2 e
3 l
4 o
5 space
6 W
7 r
8 d

Мне нужно найти такой массив, используя iTextSharp, чтобы расшифровать строковые токены.

Спасибо

Ответы [ 2 ]

1 голос
/ 28 января 2011

Спасибо, Марк за ваш ответ:

Вы ужасно правы. Поэтому я попытался заглянуть под прикрытие, по какой стратегии. GetResultantText, как вы предложили мне, без особого успеха. Моя конечная цель - получить координаты каждого слова в PDF-файле. Поэтому я попробовал стратегию LocationTextExtractionStrategy, которая кажется разумной отправной точкой.

Я могу красиво отобразить текст, но я не знаю, как получить координаты каждого слова или фрагмента. Мне нужно было бы получить доступ к чему-то вроде массива locationalResult (если такой массив существует), но я не знаю, как.

Вот мой код (VB.net):

Public Sub ParseLocation(ByVal sourcePDF As String)
    Dim reader As New iTextSharp.text.pdf.PdfReader(sourcePDF)
    Dim parser As New iTextSharp.text.pdf.parser.PdfReaderContentParser(reader)
    Dim strategy As parser.LocationTextExtractionStrategy
    Dim sResult As String

    For i As Integer = 1 To reader.NumberOfPages
        strategy = parser.ProcessContent(i, New LocationTextExtractionStrategy)
        sResult = strategy.GetResultantText
        Debug.Print(iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(reader, i, strategy))
        Debug.Print(sResult)

        strategy = parser.ProcessContent(i, New LocationTextExtractionStrategy)
        Debug.Print(strategy.GetResultantText())
    Next i
End Sub
0 голосов
/ 28 января 2011

11 0 obj <> даже недопустимый синтаксис PDF ... (или это?) Пустой словарь выглядит как <<>>.Я подозреваю, что вам не хватает одной или двух деталей.

Запись кодирования должна быть словарем или строкой.Эрк!<> является допустимой пустой строкой.Такие строки представляют собой байты, закодированные в виде шестнадцатеричных значений ... <0102030304050604070308> -> "Hello World" в вашем примере кодирования.

OTOH, запись кодирования может быть только именем или словарем (PdfName или PdfDictionary в iText-говорящем), поэтому, даже если это действительно пустая шестнадцатеричная строка, она по-прежнему недействительна.

ВВ этот момент, я думаю, вы можете с радостью принять Open Source и взглянуть на то, что делает strategy.GetResultantText.

PS: Я думаю, что вы злоупотребляете PRTokenizer.Использование в потоке части потока контента - это хорошо и удобно, но использовать его для повторного анализа словарей и т. Д. Это просто накладные расходы.Эти объекты уже были проанализированы и превращены в экземпляры PdfStream, PdfString, PdfDictionary и т. Д. С использованием PRTokenizer.

PdfDictionary fontDict = magicallyFindFontDict();
PdfObject encodingObj = fontDict.getAsDirectObject(PdfName.ENCODING);
if (encodingObj == null) { //bail
} else if (encodingObj.isName()) {
  if (PdfName.WINANSIENCODING.equals(encodingObj)) {
    ...
  } else if (...) {}...

} else if (encodingObj.isDictionary()) {
  // details in 9.6.6 of ISO PDF Spec
  ...
}
...