使用iTextSharp PRTokeniser的不可读字体

时间:2011-01-21 05:55:52

标签: itextsharp

我需要使用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。因此,字符数组将是:

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

我需要使用iTextSharp找到这样一个数组,以便破译字符串标记。

由于

2 个答案:

答案 0 :(得分:1)

感谢Mark的回答:

你非常正确。因此,我试图窥探什么策略.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

答案 1 :(得分:0)

11 0 obj <>甚至不是有效的PDF语法...(或者是吗?)空字典看起来像<<>>。我怀疑你错过了一两个细节。

编码条目必须是字典或字符串。 ERK! &LT;&GT;是一个有效的空字符串。这些字符串是以十六进制值编码的字节...&lt; 0102030304050604070308&gt; - &GT;样本编码中的“Hello World”。

OTOH,编码条目可能只是名称或字典(在iText中说PdfName或PdfDictionary),所以即使它真的是一个空的十六进制字符串,它仍然无效。

在这一点上,我认为你可以高兴地拥抱开源,并在strategy.GetResultantText正在做的事情下窥探。

PS:我认为你过度使用了PRTokenizer。在内容流的流部分上使用是很好的和花花公子,但使用它来重新解析字典,这是纯粹的开销。这些对象已经被解析并转换为PdfStreamPdfStringPdfDictionary的实例,依此类推......使用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
  ...
}