我正在通过iTextSharp-5.5.7.0阅读PDF,PdfTextExtractor.GetTextFromPage()在大多数文件中运行良好,直到:sample PDF
我无法从中读取任何数字,例如:只返回' ANEU'来自' A0NE8U',他们可以在Adobe Reader中复制出来。代码在这里:
public static string ExtractTextFromPdf(string path)
{
using (PdfReader reader = new PdfReader(path))
{
StringBuilder text = new StringBuilder();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
text.Append(PdfTextExtractor.GetTextFromPage(reader, i));
}
return text.ToString();
}
}
答案 0 :(得分:2)
相关字体有一个 ToUnicode 地图,用于文本提取。不幸的是,iText(Sharp)仅部分读取它,并且数字位于映射读取之后。
详细信息:
问题的原因是AbstractCMap.addRange
的实现(我显示了iText Java代码,因为iText也有这个问题,而且我更多地参与了Java版本):
void addRange(PdfString from, PdfString to, PdfObject code) {
byte[] a1 = decodeStringToByte(from);
byte[] a2 = decodeStringToByte(to);
if (a1.length != a2.length || a1.length == 0)
throw new IllegalArgumentException("Invalid map.");
byte[] sout = null;
if (code instanceof PdfString)
sout = decodeStringToByte((PdfString)code);
int start = a1[a1.length - 1] & 0xff;
int end = a2[a2.length - 1] & 0xff;
for (int k = start; k <= end; ++k) {
a1[a1.length - 1] = (byte)k;
PdfString s = new PdfString(a1);
s.setHexWriting(true);
if (code instanceof PdfArray) {
addChar(s, ((PdfArray)code).getPdfObject(k - start));
}
else if (code instanceof PdfNumber) {
int nn = ((PdfNumber)code).intValue() + k - start;
addChar(s, new PdfNumber(nn));
}
else if (code instanceof PdfString) {
PdfString s1 = new PdfString(sout);
s1.setHexWriting(true);
++sout[sout.length - 1];
addChar(s, s1);
}
}
}
循环仅考虑from
和to
的最低有效字节中的范围。因此,对于所讨论的范围:
1 beginbfrange
<0000><01E1>[
<FFFD><FFFD><FFFD><0020><0041><0042><0043><0044>
<0045><0046><0047><0048><0049><004A><004B><004C>
...
<2248><003C><003E><2264><2265><00AC><0394><03A9>
<00B5><03C0><00B0><221E><2202><222B><221A><2211>
<220F><25CA>]
endbfrange
它只从0x00迭代到0xE1,即只有482映射的前226个条目。
CMaps实际上有一些特殊的限制,例如:在同一部分中可能最多只有100个单独的bfrange条目,并且在替代的bfrange条目语法中
n beginbfrange
srcCode1 srcCode2 dstString
endbfrange
由同一方法addRange
处理,有限制
定义此类型的范围时,字符串中最后一个字节的值应小于或等于
255 − (srcCode2 − srcCode1)
。
可能误解了这种限制使得开发人员相信,srcCode2
和srcCode1
也只会在最不重要的字节上有所不同。
但也许还有更多的限制我只是没找到......
同时(截至iText 5.5.9,针对开发SNAPSHOT测试)此问题似乎已修复。