6

我正在尝试使用 C# 中的 itextsharp 阅读PDF,它将将此 pdf 转换为 word 文件。当我尝试使用英语 pdf 时,它还需要维护 word 中的表格格式和字体,它可以完美地工作,但使用一些印度语言,如印地语、马拉地语,它就不起作用了。

 public string ReadPdfFile(string Filename)
        {

            string strText = string.Empty;
            StringBuilder text = new StringBuilder();
            try
            {
                PdfReader reader = new PdfReader((string)Filename);
                if (File.Exists(Filename))
                {
                    PdfReader pdfReader = new PdfReader(Filename);

                    for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                    {                        ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
                        string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);

                        text.Append(currentText);
                        pdfReader.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            textBox1.Text = text.ToString();
            return text.ToString(); ;
        }
4

2 回答 2

16

我检查了您的文件,特别关注您的示例“मतद|र”在文档页面的最顶层被提取为“मतदरर”。

简而言之:

您的文档本身提供了信息,例如标题行中的字形“मतद|र”代表文本“मतदरर”。您应该向文档的来源询问字体信息不会误导的文档版本。如果那是不可能的,你应该去 OCR。

详细地:

第一页的顶行是通过页面内容流中的以下操作生成的:

/9 280 Tf
(-12"!%$"234%56*5) Tj

第一行选择大小为 280 的名为/9的字体(页面开头的操作将所有内容缩放 0.05 倍;因此,您在文件中观察到的有效大小为 14 个单位)。

第二行导致打印字形。使用该字体的自定义编码在括号之间引用这些字形。

当程序试图提取文本时,它必须使用来自字体的信息从这些字形引用中推断出实际字符。

PDF 第一页上的字体/9是使用这些对象定义的:

242 0 obj<<
    /Type/Font/Name/9/BaseFont 243 0 R/FirstChar 33/LastChar 94
    /Subtype/TrueType/ToUnicode 244 0 R/FontDescriptor 247 0 R/Widths 248 0 R>>
endobj
243 0 obj/CDAC-GISTSurekh-Bold+0
endobj 
247 0 obj<<
    /Type/FontDescriptor/FontFile2 245 0 R/FontBBox 246 0 R/FontName 243 0 R
    /Flags 4/MissingWidth 946/StemV 0/StemH 0/CapHeight 500/XHeight 0
    /Ascent 1050/Descent -400/Leading 0/MaxWidth 1892/AvgWidth 946/ItalicAngle 0>>
endobj 

所以没有/Encoding元素,但至少有对/ToUnicode映射的引用。因此,提取文本的程序必须依赖给定的/ToUnicode映射。

从 (-12"!%$"234%56*5) 中提取文本时, /ToUnicode引用的流包含以下感兴趣的映射:

<21> <21> <0930>
<22> <22> <0930>
<24> <24> <091c>
<25> <25> <0020>
<2a> <2a> <0031>
<2d> <2d> <092e>
<31> <31> <0924>
<32> <32> <0926>
<33> <33> <0926>
<34> <34> <002c>
<35> <35> <0032>
<36> <36> <0030>

(已经在这里您可以看到多个字符代码映射到同一个 unicode 代码点...)

因此,文本提取必须导致:

- = 0x2d -> 0x092e = म
1 = 0x31 -> 0x0924 = त
2 = 0x32 -> 0x0926 = द
" = 0x22 -> 0x0930 = र    instead of  |
! = 0x21 -> 0x0930 = र
% = 0x25 -> 0x0020 =  
$ = 0x24 -> 0x091c = ज
" = 0x22 -> 0x0930 = र
2 = 0x32 -> 0x0926 = द
3 = 0x33 -> 0x0926 = द
4 = 0x34 -> 0x002c = ,
% = 0x25 -> 0x0020 =  
5 = 0x35 -> 0x0032 = 2
6 = 0x36 -> 0x0030 = 0
* = 0x2a -> 0x0031 = 1
5 = 0x35 -> 0x0032 = 2

因此,从第一个文档页面的标题中提取的文本 iTextSharp(以及 Adob​​e Reader!)正是该文档在其字体信息中声称的正确内容。

由于造成这种情况的原因是字体定义中的误导性映射信息,因此整个文档存在误解也就不足为奇了。

于 2013-03-22T09:27:27.880 回答
4

正如@mkl 所说,我们需要更多关于为什么事情不起作用的信息。但我可以告诉你一些可能对你有帮助的事情。

首先,SimpleTextExtractionStrategy简单。如果您阅读它的文档,您会看到:

如果 PDF 以非从上到下的方式呈现文本,这将导致文本无法真实表示它在 PDF 中的显示方式

这意味着虽然 PDF 看起来应该从上到下阅读,但它可能是以不同的顺序编写的。您引用的 PDF 实际上首先编写了第二条视线。请参阅我的帖子,了解一种更智能的文本提取策略,该策略尝试从上到下返回文本。当我在 PDF 的第一页上运行我的代码时,它似乎正确地拉出每一“行”。

其次,PDF 没有表格的概念。它们只是在某些位置绘制了文本和线条,而这些都没有相互关联。这意味着您需要计算每一行并构建您自己的表格概念,您不会在 iTextSharp 中找到任何可以为您执行此操作的代码。我个人什至不会费心尝试写一个。

第三,文本提取用于提取与字体无关的文本。如果你愿意,你必须自己建立这种逻辑。在这里查看我的帖子以获得一个非常基本的开始。

于 2013-03-13T14:11:18.643 回答