使用itextsharp阅读PDF,其中PDF语言为非英语

时间:2013-03-13 12:24:45

标签: .net c#-4.0 pdf ms-word itextsharp

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

 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(); ;
        }

2 个答案:

答案 0 :(得分:15)

我检查了你的文件,特别关注你的样本“मतद|र”被提取为文档页面最上面一行的“मतदरर”。

简而言之:

您的文档本身提供的信息包括:头行中的字形“मतद|र”代表文字“मतदरर”。您应该向文档的来源询问文档版本,其中字体信息不会产生误导。如果那是不可能的,你应该去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 映射。

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

<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(以及Adobe Reader!)从第一个文档页面上的标题中提取的正是其字体信息中声明的文档正确无误。

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

答案 1 :(得分:4)

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

首先,SimpleTextExtractionStrategy 非常简单 。如果你read the docs,你会看到:

  

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

这意味着虽然PDF看起来应该从上到下阅读,但它可能是以不同的顺序编写的。您引用的PDF实际上首先写入了第二条视觉线。查看尝试从上到下返回文本的post here for a slightly smarter text extraction strategy。当我在PDF的第一页上运行我的代码时,它似乎正确地拉出每一行“

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

第三,文本提取用于提取与字体无关的文本。如果你想要的话,你必须自己构建那个逻辑。请参阅我的post here,了解一个非常基本的开始。