Проблемы с кодированием после использования PDFBox - PullRequest
1 голос
/ 12 ноября 2019

Мне нужно

  1. извлечь текст из pdf, где я примерно использую это

    f = IOUtility.getFileForPath(filePath);
    RandomAccessFile randomAccessFile = new RandomAccessFile(f, "r");
    PDFParser parser = new PDFParser(randomAccessFile);
    parser.parse();
    cosDoc = parser.getDocument();
    pdfStripper = new PDFTextStripper();
    pdDoc = new PDDocument(cosDoc);
    pdfStripper.setStartPage(1);
    pdfStripper.setEndPage(pdDoc.getNumberOfPages());
    String parsedText = pdfStripper.getText(pdDoc);
    
  2. масштабировать PDF

    File PDFFile = IOUtility.getFileForPath(scaleConfig.getFilePath());
    document = PDDocument.load(PDFFile);
    
    for (PDPage page : document.getPages()) {
        PDRectangle cropBox = page.getCropBox();
        float tx = ((cropBox.getLowerLeftX() + cropBox.getUpperRightX()) * 0.03f) / 2;
        float ty = ((cropBox.getLowerLeftY() + cropBox.getUpperRightY()) * 0.03f) / 2;
        PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
        cs.transform(Matrix.getScaleInstance(0.97f, 0.97f));
        cs.transform(Matrix.getTranslateInstance(tx, ty));
        cs.close();
    }
    document.save(scaleConfig.getTargetFilePath());
    
  3. и, наконец, напишите что-нибудь на каждой странице PDF-файла. Я использую один из 14 поддерживаемых шрифтов, упомянутых здесь https://pdfbox.apache.org/1.8/cookbook/workingwithfonts.html. Times New Roman в этом случае.

    File PDFFile = IOUtility.getFileForPath(writeConfig.getFilePath());
    document = PDDocument.load(PDFFile);
    for (PDPage page : document.getPages()) {
        PDFBoxHelper.fixRotation(document, page);
        writeStringOnPage(document, page, writeConfig);
    }
    document.save(writeConfig.getTargetFilePath());
    

    с writeStringOnPage, выполняющим

    contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, false, true);
    WriteCoordinates writeCoordinates = WriteCoordinateFactory.buildCoordinates(writeConfig, page.getMediaBox());
    contentStream.beginText();
    // lower left x and lower left y are different after rotation so use those for your calculation
    contentStream.newLineAtOffset(writeCoordinates.getX(), writeCoordinates.getY());
    contentStream.setFont(writeConfig.getFont(), writeConfig.getFontSize());
    contentStream.setNonStrokingColor(writeConfig.getFontColor());
    contentStream.showText(writeConfig.getToWrite());
    contentStream.endText();
    

Я не учел подписи и ловил блоки по причинам компании. Я всегда закрываю contenttreams.

Большую часть времени обработанные PDF-файлы выглядят хорошо как в Chrome PDF-Viewer, Acrobat Reader, так и после их импорта в BMD. Но в некоторых конкретных случаях у меня возникают проблемы с кодировкой, и некоторые части отображаются неправильно. Весь текст, который я добавляю в PDF, постоянно отображается правильно.

Я понял, что только жирно напечатанный текст в PDF отображается неправильно, поэтому я использовал Adobe Acrobat Reader для просмотра используемых шрифтов.

eingebettete Schriften

Arial и Arial, жирный шрифт встраиваются и кодируются с помощью Identity-H. Поскольку все написано жирным шрифтом, я пришел к выводу, что весь текст, написанный на Arial, выделен жирным шрифтом. Все остальное все в порядке после обработки PDF. Я не могу добавить PDF, потому что он содержит данные о клиентах, но вот несколько примеров:

  1. Rechnungs-Nr: -> 5HFKQXQJV1U
  2. 60Tage netto (27.12.2019) -> 7DJHQHWWR

Если PDF импортирован в BMD без PDFBox-манипуляций, он отображается правильно.

Я попытался сузить проблемуиз-за только масштабирования и только записи, но проблема возникала оба раза.

Я использую PDFBox 2.017 и Java 8.

Поскольку ошибка также возникает, когда я масштабирую только используемый мной pdf PDFDebugger для сравнения исходного PDF:

orignal PDF

и PDF после его масштабирования:

scaled PDF

Единственное, что выглядит по-другому / выключено - это запись содержимого.

Когда я открываю масштабированный PDF-файл, щелкаю мышью на разделе «Шрифты» и на шрифте Arial, Bold. я получаю много предупреждений о сопоставлениях Юникода. PDF корректно отображается в PDFDebugger.

warnings

Я не эксперт PDFBox, а также со шрифтами и кодировками, поэтому любая помощь будет принята с благодарностью!

1 Ответ

1 голос
/ 20 ноября 2019

Короче говоря

Отличие заключается в том, что PDFBox сериализует имена по-разному. Но различные выходные данные в соответствии со спецификацией PDF эквивалентны, поэтому вы, очевидно, обнаружили ошибку WPViewPDF.

Разница в написании имен

В оригинальном PDF (raw.pdf) вы найдетеимена NOWFJV + Arial, полужирный и NOWFJV + Arial, Bold-WinCharSetFFFF , во всех файлах, с которыми работает PDFBox, вы найдете все вхождения этих имен вне потоков содержимого, замененные на NOWFJV+ Arial # 2CBold и NOWFJV + Arial # 2CBold-WinCharSetFFFF .

WPViewPDF не может правильно отображать текст, написанный в шрифтах с этими измененными именами. После исправления PDF-файлов обратно, чтобы в этих именах вместо запятой вместо # 2C содержалась запятая, WPViewPDF снова правильно отображает такой текст.

Я бы предположил, что WPViewPDF находит NOWFJV + Arial, полужирный в потоке контента и ожидает найти соответствующее определение шрифта в ресурсах страницы, используя идентично написанное имя, поэтому он не распознает его с именем NOWFJV + Arial # 2CBold .

Это ошибка PDFBox?

В соответствии со спецификацией PDF,

Любой символ в имени, являющийся обычным символом (кроме ЗНАКА NUMBER), должен быть написан как сам по себе или какиспользуя двухзначный шестнадцатеричный код, которому предшествует ЗНАК ЧИСЛА.

(ISO 32000-2, раздел 7.3.5 «Наименование объектов»)

Таким образом, эта замена запятых в именах последовательностями '# 2C' является полностью допустимым альтернативным способом записи этих имен.

Таким образом, нет, это не ошибка PDFBox, а, по-видимому, ошибка WPViewPDF.

...