Apache PDFBox 删除字符之间的空格
Apache PDFBox Remove Spaces between characters
我们正在使用 PDFBox 从 PDF 中提取文本。
部分PDF文本无法正确提取。
下图显示了 PDF 中的一部分作为图像:
文本提取后我们得到以下文本:
3, 8 5 EU R 1 内托 38,50 4,00 欧元
(','和'8'之间添加空格)
这是我们的代码:
PDDocument pdf = PDDocument.load(reuseableInputStream);
PDFTextStripper pdfStripper = new PDFTextStripper();
pdfStripper.setSortByPosition(true);
String text = pdfStripper.getText(pdf);
我们尝试使用 PDFTextStripper 属性 'AverageCharTolerance' 和 'SpacingTolerance',但没有任何积极效果。
替代库 'iText' 正确提取文本,字符之间没有空格。但是因为license的问题不能使用
有什么想法吗?谢谢。
编辑: 我们使用的是 1.8.9 版。我们也尝试了快照版本 2.0.0 没有效果。
原因
检查 OP 提供的文件后发现问题是由 额外的 space 实际存在 引起的!从同一个起始位置抽取的字符串有多个;在每个位置,这些字符串中最多有一个具有非 space 字符。因此,PDF 查看器输出看起来不错,但作为文本提取器的 PDFBox 会尝试使用找到的所有字符,包括那些额外的 space 个字符。
可以使用具有此内容流的 PDF 重现该行为,F0 为 Courier:
BT
/F0 9 Tf
100 500 Td
( 2 Netto 5,00 EUR 3,00) Tj
0 0 Td
( 2882892 ENERGIZE LR6 Industrial 2,50 EUR 1) Tj
ET
在 PDF 查看器中,它看起来像这样:
从 Adobe 复制和粘贴 Reader 结果
2 2 8 8 2 8 9 2 E N E R G I Z E L R 6 I n d u s t r i a l 2 , 5 0 E U R 1 Netto 5,00 EUR 3,00
使用 PDFBox 进行常规提取会导致
2 2 8 8 2 89 2 E N E RG IZ E L R 6 I n du s t ri a l 2 ,5 0 EU R 1 Netto 5,00 EUR 3,00
因此,不仅 PDFBox 在这里有问题,这两个输出看起来不同,而且额外的 space 无论如何都是问题。
我建议告诉这些 PDF 的制作者它们很难 post 处理,即使是像 Adobe Reader.
这样广泛使用的软件也是如此
解决方法
为了从中提取一些有意义的东西,我们必须以某种方式忽略(实际存在!)额外的 spaces。由于无法临时知道哪些 spaces 可以稍后使用,哪些不能,我们只是删除所有并希望 PDFBox 在必要时添加 spaces:
String extractNoSpaces(PDDocument document) throws IOException
{
PDFTextStripper stripper = new PDFTextStripper()
{
@Override
protected void processTextPosition(TextPosition text)
{
String character = text.getCharacter();
if (character != null && character.trim().length() != 0)
super.processTextPosition(text);
}
};
stripper.setSortByPosition(true);
return stripper.getText(document);
}
(ExtractWithoutExtraSpaces.java)
将此方法与测试文档一起使用我们得到:
2 2882892 ENERGIZE LR6 Industrial 2,50 EUR 1 Netto 5,00 EUR 3,00
不同的文本提取器
The alternative libary 'iText' extract the text correctly without spaces between the characters
这是因为 iText 是逐个字符串而不是逐个字符地提取文本。此过程有其自身的风险,但在这种情况下会产生一些开箱即用的东西。
在较新版本的 PDFBox 上,解决方法不起作用。
但是您可以解决问题 space 并获得相同的结果,只需像这样设置 PDFTextStripper:
PDFTextStripper strippet = new PDFTextStripper();
stripper.setWordSeparator("");
我们正在使用 PDFBox 从 PDF 中提取文本。
部分PDF文本无法正确提取。 下图显示了 PDF 中的一部分作为图像:
文本提取后我们得到以下文本:
3, 8 5 EU R 1 内托 38,50 4,00 欧元
(','和'8'之间添加空格)
这是我们的代码:
PDDocument pdf = PDDocument.load(reuseableInputStream);
PDFTextStripper pdfStripper = new PDFTextStripper();
pdfStripper.setSortByPosition(true);
String text = pdfStripper.getText(pdf);
我们尝试使用 PDFTextStripper 属性 'AverageCharTolerance' 和 'SpacingTolerance',但没有任何积极效果。
替代库 'iText' 正确提取文本,字符之间没有空格。但是因为license的问题不能使用
有什么想法吗?谢谢。
编辑: 我们使用的是 1.8.9 版。我们也尝试了快照版本 2.0.0 没有效果。
原因
检查 OP 提供的文件后发现问题是由 额外的 space 实际存在 引起的!从同一个起始位置抽取的字符串有多个;在每个位置,这些字符串中最多有一个具有非 space 字符。因此,PDF 查看器输出看起来不错,但作为文本提取器的 PDFBox 会尝试使用找到的所有字符,包括那些额外的 space 个字符。
可以使用具有此内容流的 PDF 重现该行为,F0 为 Courier:
BT
/F0 9 Tf
100 500 Td
( 2 Netto 5,00 EUR 3,00) Tj
0 0 Td
( 2882892 ENERGIZE LR6 Industrial 2,50 EUR 1) Tj
ET
在 PDF 查看器中,它看起来像这样:
从 Adobe 复制和粘贴 Reader 结果
2 2 8 8 2 8 9 2 E N E R G I Z E L R 6 I n d u s t r i a l 2 , 5 0 E U R 1 Netto 5,00 EUR 3,00
使用 PDFBox 进行常规提取会导致
2 2 8 8 2 89 2 E N E RG IZ E L R 6 I n du s t ri a l 2 ,5 0 EU R 1 Netto 5,00 EUR 3,00
因此,不仅 PDFBox 在这里有问题,这两个输出看起来不同,而且额外的 space 无论如何都是问题。
我建议告诉这些 PDF 的制作者它们很难 post 处理,即使是像 Adobe Reader.
这样广泛使用的软件也是如此解决方法
为了从中提取一些有意义的东西,我们必须以某种方式忽略(实际存在!)额外的 spaces。由于无法临时知道哪些 spaces 可以稍后使用,哪些不能,我们只是删除所有并希望 PDFBox 在必要时添加 spaces:
String extractNoSpaces(PDDocument document) throws IOException
{
PDFTextStripper stripper = new PDFTextStripper()
{
@Override
protected void processTextPosition(TextPosition text)
{
String character = text.getCharacter();
if (character != null && character.trim().length() != 0)
super.processTextPosition(text);
}
};
stripper.setSortByPosition(true);
return stripper.getText(document);
}
(ExtractWithoutExtraSpaces.java)
将此方法与测试文档一起使用我们得到:
2 2882892 ENERGIZE LR6 Industrial 2,50 EUR 1 Netto 5,00 EUR 3,00
不同的文本提取器
The alternative libary 'iText' extract the text correctly without spaces between the characters
这是因为 iText 是逐个字符串而不是逐个字符地提取文本。此过程有其自身的风险,但在这种情况下会产生一些开箱即用的东西。
在较新版本的 PDFBox 上,解决方法不起作用。 但是您可以解决问题 space 并获得相同的结果,只需像这样设置 PDFTextStripper:
PDFTextStripper strippet = new PDFTextStripper();
stripper.setWordSeparator("");