Apache PDFBox删除字符之间的空格

Tob*_*asH 5 text-extraction pdf-parsing pdfbox

我们使用PDFBox从PDF中提取文本.

某些PDF文本无法正确提取.下图显示了PDF作为图像的一部分:

在此输入图像描述

文本提取后,我们得到以下文本:
3,8 5 EU R 1 Netto 38,50 EUR 4,00
(在','和'8'之间添加空格)

这是我们的代码:

            PDDocument pdf = PDDocument.load(reuseableInputStream);
            PDFTextStripper pdfStripper = new PDFTextStripper();
            pdfStripper.setSortByPosition(true);
            String text = pdfStripper.getText(pdf);
Run Code Online (Sandbox Code Playgroud)

我们试图使用PDFTextStripper属性'AverageCharTolerance'和'SpacingTolerance'没有正面效果.

备用库'iText'正确提取文本,字符之间没有空格.但由于许可证问题,我们无法使用它.

有任何想法吗?谢谢.

编辑:我们使用的是1.8.9版本.我们还尝试了快照版本2.0.0而没有任何效果.

mkl*_*mkl 6

原因

检查OP提供的文件结果证明问题是由实际存在的额外空间引起的!从同一起始位置绘制了多个字符串; 在每个位置,其中一个字符串中的一个具有非空格字符.因此,PDF查看器输出看起来很好,但PDFBox作为文本提取器尝试使用找到的所有字符,包括那些额外的空格字符.

可以使用带有此内容流的PDF重现该行为,其中F0Courier:

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
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

因此,不仅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);
}
Run Code Online (Sandbox Code Playgroud)

(ExtractWithoutExtraSpaces.java)

将此方法与测试文档一起使用,我们得到:

2 2882892 ENERGIZE LR6 Industrial 2,50 EUR 1 Netto 5,00 EUR 3,00
Run Code Online (Sandbox Code Playgroud)

不同的文本提取器

备用库'iText'正确提取文本,字符之间没有空格

这是因为iText按字符串提取文本字符串,而不是逐个字符.这个过程有其自身的危险,但在这种情况下会产生一些更实用的开箱即用的功能.