原因
检查 OP 提供的文件,结果发现问题是由实际存在的额外空间引起的!从同一个起始位置抽取多个字符串;在每个位置,这些字符串中最多有一个具有非空格字符。因此,PDF 查看器的输出看起来不错,但作为文本提取器的 PDFBox 会尝试使用找到的所有字符,包括那些额外的空格字符。
可以使用带有此内容流的 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 在这里有问题,这两个输出看起来不同,但额外的空格都是问题。
我建议告诉这些 PDF 的制作者,它们很难进行后期处理,即使对于像 Adobe Reader 这样广泛使用的软件也是如此。
一种解决方法
为了从中提取一些有意义的东西,我们必须以某种方式忽略(实际存在的!)额外的空间。由于无法临时知道哪些空格可以稍后使用,哪些不可以,我们只需删除所有空格并希望 PDFBox 在必要时添加空格:
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
不同的文本提取器
替代库“iText”正确提取文本,字符之间没有空格
这是由于 iText 是逐个字符串而不是逐个字符地提取文本字符串。此过程有其自身的危险,但在这种情况下会产生一些开箱即用的更有用的东西。