iTextSharp无法读取此PDF中的数字

时间:2015-09-28 03:26:44

标签: pdf itextsharp itext

我正在通过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();
    }
}

1 个答案:

答案 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);
        }
    }
}

循环仅考虑fromto的最低有效字节中的范围。因此,对于所讨论的范围:

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)

可能误解了这种限制使得开发人员相信,srcCode2srcCode1也只会在最不重要的字节上有所不同。

但也许还有更多的限制我只是没找到......

同时(截至iText 5.5.9,针对开发SNAPSHOT测试)此问题似乎已修复。