【问题标题】:Fails to parse Hebrew text from pdf using iText 7 with .net无法使用 iText 7 和 .net 解析来自 pdf 的希伯来语文本
【发布时间】:2020-01-21 16:19:32
【问题描述】:

我正在尝试在 .NET CORE 2.1 上使用 iText 7 阅读包含多页的 PDF 文件 以下是我的代码:

Rectangle rect = new Rectangle(0, 0, 1100, 1100);
LocationTextExtractionStrategy strategy = new LocationTextExtractionStrategy();
inputStr = PdfTextExtractor.GetTextFromPage(pdfDocument.GetPage(i), strategy);

inputStr 获取以下字符串:

"\u0011\v\u000e\u0012\u0011\v\f)(*).=*%'\f*).5?5.5*.\a \u0011\u0002\u001b\u0001!\u0016\u0012\u001a!\u0001\u0015\u001a \u0014\n\u0015\u0017\u0001(\u001b)\u0001)\u0016\u001c*\u0012\u0001\u001d\u001a \u0016* \u0015\u0001\u0017\u0016\u001b\u001a(\n,\u0002>&\u00...

在文本可视化器中,它看起来像这样:

)(*).=*%'*).5?5.5*. !! 
())* * (
,>&2*06) 2.-=9 )=&,

2..*0.5<.?
.110
)<1,3
    2.3*1>?)10/6
     (& >(*,1=0>>*1?

    2.63)&*,..*0.5

   206)&13'?*9*<
    *-5=0>
  ?*&..,?)..*0.5

我似乎无法解析编码,或者我无法读取/解析 PDF 级别的特定自定义编码。

查看文档属性,在字体下它显示以下内容:

任何想法如何正确解析文档?

谢谢 亚尼夫

【问题讨论】:

  • 您好,您可以发布 PDF 进行分析吗?可能是文件中的问题或库中的错误
  • 首先猜测一下,您在 Adob​​e Reader 中从 pdf 中复制和粘贴了什么?
  • @AlexeySubach 我无法发布 PDF,因为它包含敏感数据。我会尝试屏蔽敏感数据并发布。
  • @mkl 复制粘贴完美
  • 在这种情况下,需要pdf进行进一步分析。

标签: asp.net-core-2.0 itext7


【解决方案1】:

共享文件分析

file1_copyPasteWorks.pdf

这里的字体定义有一个无效的 ToUnicode 条目:

/ToUnicode/Identity-H

ToUnicode 值指定为

包含将字符代码映射到 Unicode 值的 CMap 文件的流

(ISO 32000-2,表 119 - Type 0 字体字典中的条目)

Identity-H 是一个名称,而不是一个

尽管如此,Adobe Reader 会解释这个名称,而且对于任何以 Identity- 开头的名称,显然都假定字体的文本编码为 UCS-2(本质上是 UTF-16)。由于文档中使用的字符代码确实如此,即使出于错误的原因,复制和粘贴也有效。 (没有这个 ToUnicode 值,Adobe Reader 也会返回废话。)

另一方面,iText 7 映射到 Unicode 首先遵循 Encoding 值,但结果出乎意料。

因此,在这种情况下,Adobe Reader 通过将含义解释为无效的数据片段(如果不这样做也会返回无意义的数据),从而获得更好的结果。

file2_copyPasteFails.pdf

此处的字体定义具有有效但不完整的 ToUnicode 映射,其中仅包含所用西欧字符的条目,但不包含希伯来语字符的条目。它们没有编码条目。

此处的 Adob​​e Reader 和 iText 7 都信任 ToUnicode 映射,因此无法映射希伯来字形。

如何解析

file1_copyPasteWorks.pdf

对于这个文件,“问题”是 iText 7 应用了 Encoding 映射。因此,为了解码文本,可以暂时将 Encoding 映射替换为标识映射:

for (int i = 1; i <= pdfDocument.GetNumberOfPages(); i++)
{
    PdfPage page = pdfDocument.GetPage(i);
    PdfDictionary fontResources = page.GetResources().GetResource(PdfName.Font);
    foreach (PdfObject font in fontResources.Values(true))
    {
        if (font is PdfDictionary fontDict)
            fontDict.Put(PdfName.Encoding, PdfName.IdentityH);
    }

    string output = PdfTextExtractor.GetTextFromPage(page);
    // ... process output ...
}

此代码显示文件 1 的希伯来语字符。

file2_copyPasteFails.pdf

在这里我没有快速的解决方法。您可能想要分析多个此类 PDF。如果它们都以相同的方式对希伯来字符进行编码,您可以从中创建自己的 ToUnicode 映射并将其注入到上述字体中。

【讨论】:

  • 顺便问一下,当您读取文件时,您能够读取 RTL 吗?所有输入对我来说都是 LTR...
  • 它是 LTR。必须对字符串output 进行相应的后处理,必须反转具有 RTL 脚本中字符的最大子部分,或者(如果在最重要的 RTL 上下文中)必须反转整个字符串,然后使用最大子部分其中 LTR 脚本中的字符必须再次反转。
猜你喜欢
  • 2019-07-25
  • 2011-08-16
  • 2011-09-02
  • 1970-01-01
  • 2011-09-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 2018-06-15
相关资源
最近更新 更多