Apache PDFBox Удалить пробелы между символами

Мы используем PDFBox для извлечения текста из PDF.

Некоторые PDF-текст не могут быть извлечены правильно. Следующее изображение показывает часть из PDF в виде изображения:

После извлечения текста мы получаем следующий текст:
3, 8 5 EU R 1 Нетто 38,50 EUR 4,00
(Пробелы добавляются между ',' и '8')

Вот наш код:

            PDDocument pdf = PDDocument.load(reuseableInputStream);
            PDFTextStripper pdfStripper = new PDFTextStripper();
            pdfStripper.setSortByPosition(true);
            String text = pdfStripper.getText(pdf);

Мы попытались поиграть с атрибутами PDFTextStripper "AverageCharTolerance" и "SpacingTolerance" без какого-либо положительного эффекта.

Альтернативная библиотека 'iText' правильно извлекает текст без пробелов между символами. Но мы не можем использовать его из-за проблем с лицензией.

Есть идеи? Спасибо.

РЕДАКТИРОВАТЬ: Мы используем версию 1.8.9. Мы попробовали также снимок версии 2.0.0 безрезультатно.

2 ответа

Решение

Причина

Изучив файл, предоставленный OP, выясняется, что проблема вызвана наличием лишних пробелов! Есть несколько строк, взятых из одной начальной позиции; в каждой позиции не более одной из этих строк имеет непустой символ. Таким образом, вывод средства просмотра PDF выглядит хорошо, но PDFBox как средство извлечения текста пытается использовать все найденные символы, включая эти дополнительные пробелы.

Поведение может быть воспроизведено, используя PDF с этим потоком контента с F0, являющимся Курьером:

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 извлекает текстовую строку за строкой, а не символ за символом. Эта процедура имеет свои собственные риски, но в этом случае приводит к чему-то более полезному из коробки.

В более новых версиях PDFBox обходной путь не работает. Но вы можете исправить проблемное пространство и добиться того же результата, просто установив свой PDFTextStripper следующим образом:

      PDFTextStripper strippet = new PDFTextStripper();
stripper.setWordSeparator("");
Другие вопросы по тегам