我需要使用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找到这样一个数组,以便破译字符串标记。
由于
答案 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
正在做的事情下窥探。
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
...
}