使用itextsharp阅读PDF,其中PDF语言是非英语的
我正在尝试使用C#中的itextsharp来读取这个 PDF,它将把这个pdf转换成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(); ; }
我仔细检查了你的文件,特别关注你的样本“मतद|र”被提取为“मतदर”在文档页面的最上面一行。
简而言之:
您的文档本身提供的信息,例如头条中的字形“मतद|र”代表文本“मतदर”。 你应该问你的文件来源的文件版本,其中的字体信息是没有误导的。 如果这是不可能的,你应该去OCR。
详细:
第一页的第一行是由页面内容stream中的以下操作生成的:
/9 280 Tf (-12"!%$"234%56*5) Tj
第一行select大小为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
所以没有/编码的元素,但至less有一个/ ToUnicode地图的引用。 因此,提取文本的程序必须依赖于给定的/ ToUnicode映射。
从/ ToUnicode引用的stream在从(-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!)从第一个文档页面的标题中提取正是其字体信息中声明的文档是正确的。
由于这个原因是字体定义中误导性的映射信息,所以整个文档都有错误的解释并不奇怪。
正如@mkl所说的,我们需要更多的信息来说明为什么事情没有起作用。 但是我可以告诉你一些可能对你有帮助的事情。
首先, SimpleTextExtractionStrategy
非常简单 。 如果你阅读文档 ,你会看到:
如果PDF以非自上而下的方式呈现文本,则这将导致文本不能真实地表示它在PDF中的显示方式
这意味着尽pipePDF可能看起来应该从上到下阅读,但也可能是按不同的顺序编写的。 您参考的PDF实际上有第一个写的第二条视线。 看到我的post在这里,一个稍微更聪明的文本提取策略 ,试图从上到下返回文本。 当我在你的PDF的第一页上运行我的代码时,它似乎正确地拉出每个“行”。
其次,PDFs没有表格的概念。 他们只是在特定位置绘制文字和线条,而这些都不相关。 这意味着你将需要计算每一行,并build立自己的表的概念,iTextSharp中找不到任何代码为你做这个。 我个人甚至不打算写一个。
第三,文本提取是为了拉取与字体无关的文本。 如果你想要的话,你必须build立自己的逻辑。 在这里看到我的post是一个非常基本的开始。