我试图找到一种用iTextSharp提取右到左语言字符串的解决方案,但找不到任何方法。是否可以使用iTextSharp从pdf文件中提取RightToLeft语言字符串?谢谢
编辑:这段代码有很好的效果:
private void writePdf2()
{
using (var document = new Document(PageSize.A4))
{
var writer = PdfWriter.GetInstance(document, new FileStream(@"C:\Users\USER\Desktop\Test2.pdf", FileMode.Create));
document.Open();
FontFactory.Register("c:\\windows\\fonts\\tahoma.ttf");
var tahoma = FontFactory.GetFont("tahoma", BaseFont.IDENTITY_H);
var reader = new PdfReader(@"C:\Users\USER\Desktop\Test.pdf");
int intPageNum = reader.NumberOfPages;
string text = null;
for (int i = 1; i <= intPageNum; i++)
{
text = PdfTextExtractor.GetTextFromPage(reader, i, new LocationTextExtractionStrategy());
text = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(text.ToString()));
text = new UnicodeCharacterPlacement
{
Font = new System.Drawing.Font("Tahoma", 12)
}.Apply(text);
File.WriteAllText("page-" + i + "-text.txt", text.ToString());
}
reader.Close();
ColumnText.ShowTextAligned(
canvas: writer.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk("Test. Hello world. Hello people. سلام. کلمه سلام. سلام مردم", tahoma)),
//phrase: new Phrase(new Chunk(text, tahoma)),
x: 300,
y: 300,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
}
System.Diagnostics.Process.Start(@"C:\Users\USER\Desktop\Test2.pdf");
}
但是短语: new Phrase(new Chunk(text, tahoma))并没有对PDF中的所有字符串都有正确的输出。因此,我使用PdfStamper制作了一个适用于iTextSharp中的PdfReader的PDF。
由于OP最初无法提供示例文件,我首先尝试用iTextSharp自己生成的文件重现该问题。
我的测试方法首先使用列文本创建PDF。ShowTextAligned
与字符串常量对齐,根据OP返回一个好结果。然后提取该文件的文本内容。最后,它创建了第二个PDF,其中包含使用goodColumnText创建的一行。ShowTextAligned
使用字符串常量调用,然后使用ColumnText创建几行。ShowTextAligned
,使用从OP代码(UTF8编码和-解码;应用UnicodeCharacterPlacement
)执行的带或不带后处理指令的提取字符串。
我无法立即找到OP使用的UnicodeCharacterPlacement
类。所以我在谷歌上搜索了一下,在这里找到了一个这样的类。我希望这基本上就是OP使用的类。
public void ExtractTextLikeUser2509093()
{
string rtlGood = @"C:\Temp\test-results\extract\rtlGood.pdf";
string rtlGoodExtract = @"C:\Temp\test-results\extract\rtlGood.txt";
string rtlFinal = @"C:\Temp\test-results\extract\rtlFinal.pdf";
Directory.CreateDirectory(@"C:\Temp\test-results\extract\");
FontFactory.Register("c:\\windows\\fonts\\tahoma.ttf");
Font tahoma = FontFactory.GetFont("tahoma", BaseFont.IDENTITY_H);
// A - Create a PDF with a good RTL representation
using (FileStream fs = new FileStream(rtlGood, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (Document document = new Document())
{
PdfWriter pdfWriter = PdfWriter.GetInstance(document, fs);
document.Open();
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk("Test. Hello world. Hello people. سلام. کلمه سلام. سلام مردم", tahoma)),
x: 500,
y: 300,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
}
}
// B - Extract the text for that good representation and add it to a new PDF
String textA, textB, textC, textD;
using (PdfReader pdfReader = new PdfReader(rtlGood))
{
textA = PdfTextExtractor.GetTextFromPage(pdfReader, 1, new LocationTextExtractionStrategy());
textB = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(textA.ToString()));
textC = new UnicodeCharacterPlacement
{
Font = new System.Drawing.Font("Tahoma", 12)
}.Apply(textA);
textD = new UnicodeCharacterPlacement
{
Font = new System.Drawing.Font("Tahoma", 12)
}.Apply(textB);
File.WriteAllText(rtlGoodExtract, textA + "\n\n" + textB + "\n\n" + textC + "\n\n" + textD + "\n\n");
}
using (FileStream fs = new FileStream(rtlFinal, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (Document document = new Document())
{
PdfWriter pdfWriter = PdfWriter.GetInstance(document, fs);
document.Open();
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk("Test. Hello world. Hello people. سلام. کلمه سلام. سلام مردم", tahoma)),
x: 500,
y: 600,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk(textA, tahoma)),
x: 500,
y: 550,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk(textB, tahoma)),
x: 500,
y: 500,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk(textC, tahoma)),
x: 500,
y: 450,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
ColumnText.ShowTextAligned(
canvas: pdfWriter.DirectContent,
alignment: Element.ALIGN_RIGHT,
phrase: new Phrase(new Chunk(textD, tahoma)),
x: 500,
y: 400,
rotation: 0,
runDirection: PdfWriter.RUN_DIRECTION_RTL,
arabicOptions: 0);
}
}
}
最终结果是:
因此,
>
我无法重现这个问题。对我来说,最后两个变体的阿拉伯内容看起来都与原始行相同。特别是,我无法观察到从 "سلام" 到 "سالم". 的切换。最有可能的是PDFC:\User\USER\Desktop\Test.pdf
(OP从其中提取了测试中的文本)在某种程度上是特殊的,因此从它中提取的文本会使用该切换。
将UnicodeCharacterPlacement
类应用于提取的文本是必要的,这样才能使其按正确的顺序排列。
另一条后处理线,
text = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(text.ToString()));
没有任何区别,不应使用。
为了进一步分析,我们需要PDFC:\Users\USER\Desktop\Test。pdf
。
最终OP可以提供一个示例PDF,salamword.pdf:
我用“PrimoPDF”创建了一个包含以下内容的PDF文件:“Test.Hello world.Hello people。
接下来我读了这个PDF文件。然后我收到了这个输出:“Test.Hello world.Hello people.م.م1583;م”。
事实上,我可以复制这种行为。所以我分析了阿拉伯文字的编码方式。。。
以下是一些背景信息:
PDF中的字体可以有一个完全自定义的编码(在目前的情况下确实有)。特别是嵌入式子集通常是通过选择字符来生成的,例如页面上使用的给定字体的第一个字符被编码为1
,第二个不同的字符被编码为2
,第三个不同的字符被编码为3
等等。
因此,简单地提取绘制文本的代码一点帮助都没有(参见下面手头文件中的示例)。但是PDF中的字体可以带来一些额外的信息,允许提取器将代码映射到Unicode值。这些信息可能是
PDF规范描述了一种使用ToUnicode和带有标准名称的编码信息从PDF中提取文本的方法,并在适用的情况下将ActualText作为替代方式呈现。iTextSharp文本提取代码使用标准名称实现ToUnicode/编码方法。
PDF规范中的标准名称是取自Adobe标准拉丁字符集的字符名称,以及符号字体中的命名字符集。
在手头的文件中:
让我们看看用Arial写的行中的阿拉伯文本。这里用于字形的代码是:
01 02 03 04 05 01 02 06 07 01 08 02 06 07 01 09 05 00B01 08 02 06 07
这看起来很像使用了如上所述的特殊编码。因此,仅使用这些信息毫无帮助。
因此,让我们看看嵌入式Arial子集的ToUnicode映射:
<01><01><0020>
<02><02><0645>
<03><03><062f>
<04><04><0631>
<08><08><002e>
<0c><0c><0028>
<0d><0d><0077>
<0e><0e><0069>
<0f><0f><0074>
<10><10><0068>
<11><11><0041>
<12><12><0072>
<13><13><0061>
<14><14><006c>
<15><15><0066>
<16><16><006f>
<17><17><006e>
<18><18><0029>
这将01
映射到0020
,02
映射到0645
,03
映射到062f
,04
映射到0631
,08
映射到002e
,等等。但它不会将05
,06
,07
映射到任何东西。
所以ToUnicode映射只对某些代码有帮助。
现在让我们看看相关的编码
29 0 obj
<</Type/Encoding
/BaseEncoding/WinAnsiEncoding
/Differences[ 1
/space/uni0645/uni062F/uni0631
/uni0645.init/uni06440627.fina/uni0633.init/period
/uni0647.fina/uni0644.medi/uni06A9.init/parenleft
/w/i/t/h
/A/r/a/l
/f/o/n/parenright ]
>>
endobj
编码是基于WinAnsiEn编码的,但是所有感兴趣的代码都在差异中重新映射。在那里我们找到了许多标准字形名称(即取自Adobe标准拉丁字符集和符号字体中命名字符集的字符名称),如空间、句号、w、i、t等。;但是我们也找到了几个非标准名称,如uni0645、uni06440627.fina等。
这些名称似乎使用了一个方案,uni0645表示Unicode代码点0645处的字符,uni06440627。fina很可能以某种最终形式以某种顺序表示Unicode代码点0644和0627处的字符。但根据PDF规范提供的方法,这些名称对于文本提取来说仍然是非标准的。
此外,文件中根本没有ActualText条目。
因此,只提取“م.م.مدم”的原因是,只有对于这些字形,PDF中才有标准PDF文本提取方法的适当信息。
顺便说一下,如果你收到了
TL;博士
示例文件根本不包含使用PDF规范描述的方法提取文本所需的信息,该方法是由iTextSharp实现的。
问题内容: 我需要使用iText从pdf文件中提取文本。 问题是:一些pdf文件包含2列,当我提取文本时,我得到一个文本文件,其中的列作为结果合并(即同一行中两列的文本) 这是代码: 你能帮我完成这个任务吗? 问题答案: 我是iText文本提取子系统的作者。您需要做的是开发自己的文本提取策略(如果您看一下如何实现的话,就会发现您可以提供可插拔的策略)。 您将如何确定列的开始和停止位置完全取决于您-
我有一个签名的PDF文件。有了这个功能,它利用了iTextSharp库,我找到了证书p7m签名: 现在...我如何提取与签名相关的图像(位图)?可能吗?谢谢,路易吉
问题内容: 我正在寻找有关如何使用带有Python的PDFMiner从PDF文件提取文本的文档 或 示例。 看来PDFMiner更新了他们的API,我发现的所有相关示例都包含过时的代码(类和方法已更改)。我发现的那些使从PDF文件提取文本的任务更加容易的库正在使用旧的PDFMiner语法,因此我不确定如何执行此操作。 照原样,我只是在查看源代码,以查看是否可以解决。 问题答案: 这是一个使用当前版
问题内容: 我正在尝试使用提取此 PDF文件中包含的文本。 我正在使用PyPDF2模块,并具有以下脚本: 运行代码时,得到以下输出,该输出与PDF文档中包含的输出不同: 如何提取PDF文档中的文本? 问题答案: 要从PDF提取文本,请使用以下代码
我有一个列表。pdf,ppt,pptx,xls,xlsx,doc和。docx文件,现在想在这些文件中查找电子邮件地址。我的问题是如何从这些文件中智能地提取计划文本。目前我正在使用Apache POI,我对每种类型的文件都有一个单一的方法,是否有一个更短、更优雅的位置来做这件事?也许还可以处理。ODT、.ODP、.ODS文件?如何从。pdf,ppt,pptx,xls,xlsx,doc和.docx文件
问题内容: 我想使用Apache PDFBox从给定的PDF文件中提取文本。 我写了这段代码: 但是,出现以下错误: 我在类路径中添加了pdfbox-1.8.5.jar和fontbox-1.8.5.jar。 编辑 我添加到程序的开头。 我运行了它,然后出现了与上述相同的错误,并且未出现在控制台中。 因此,我认为我对类路径或其他东西有疑问。 谢谢。 问题答案: 我执行了您的代码,它工作正常。也许您的