Статьи

Apache PDFBox 2

Apache PDFBox 2 был выпущен ранее в этом году, и с тех пор были выпущены Apache PDFBox 2.0.1 и Apache PDFBox 2.0.2 . Apache PDFBox является открытым исходным кодом ( Apache License Version 2 ) и основан на Java (и поэтому прост в использовании с широким спектром языков программирования, включая Java , Groovy , Scala , Clojure , Kotlin и Ceylon ). Apache PDFBox может использоваться любым из этих или других языков на основе JVM для чтения, записи и работы с документами PDF .

Apache PDFBox 2 содержит множество исправлений ошибок в дополнение к выполненным задачам и некоторым новым функциям. Для Apache PDFBox 2 теперь требуется Java SE 6 ( J2SE 5 был минимальным для Apache PDFBox 1.x ). Существует руководство по миграции Migration to PDFBox 2.0.0 , в котором подробно описываются многие различия между PDFBox 1.8 и PDFBox 2.0, включая обновленные зависимости ( Bouncy Castle 1.53 и Apache Commons Logging 1.2 ) и «внесение изменений в библиотеку» в PDFBox 2.

PDFBox может быть использован для создания PDF-файлов. Следующий листинг кода адаптирован из примера Apache PDFBox 1.8 «Создать пустой PDF» в примерах «Поваренная книга» по созданию документов . Упомянутый пример явно закрывает экземпляр PDDocument и, вероятно, делает это для тех, кто использует версию Java до JDK 7. Однако для пользователей Java 7 попытка с ресурсами является лучшим вариантом для обеспечения того, PDDocument экземпляр PDDocument закрыт. и это поддерживается, потому что PDDocument реализует AutoCloseable .

Создание (Пусто) PDF

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
/**
 * Demonstrate creation of an empty PDF.
 */
private void createEmptyDocument()
{
   try (final PDDocument document = new PDDocument())
   {
      final PDPage emptyPage = new PDPage();
      document.addPage(emptyPage);
      document.save("EmptyPage.pdf");
   }
   catch (IOException ioEx)
   {
      err.println(
         "Exception while trying to create blank document - " + ioEx);
   }
}

Следующий список кода адаптирован из примера Apache PDFBox 1.8 «Hello World, использующий базовый шрифт PDF» в примерах «Cookbook» создания документа . Наиболее существенным изменением в этом листинге по сравнению с этим примером 1.8 Cookbook является замена устаревших методов PDPageContentStream.moveTextPositionByAmount (float, float) и PDPageContentStream.drawString (String) на PDPageContentStream.newLineAtOffset (float, float) и PDPageConTextring (SDR). ,

Создание простого PDF со шрифтом

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * Create simple, single-page PDF "Hello" document.
 */
private void createHelloDocument()
{
   final PDPage singlePage = new PDPage();
   final PDFont courierBoldFont = PDType1Font.COURIER_BOLD;
   final int fontSize = 12;
   try (final PDDocument document = new PDDocument())
   {
      document.addPage(singlePage);
      final PDPageContentStream contentStream = new PDPageContentStream(document, singlePage);
      contentStream.beginText();
      contentStream.setFont(courierBoldFont, fontSize);
      contentStream.newLineAtOffset(150, 750);
      contentStream.showText("Hello PDFBox");
      contentStream.endText();
      contentStream.close();  // Stream must be closed before saving document.
 
      document.save("HelloPDFBox.pdf");
   }
   catch (IOException ioEx)
   {
      err.println(
         "Exception while trying to create simple document - " + ioEx);
   }
}

Следующий листинг кода демонстрирует разбор текста из PDF с использованием Apache PDFBox. Эта чрезвычайно простая реализация разбирает весь текст в одну String используя PDFTextStripper.getText (PDDocument) . В большинстве реалистичных ситуаций я бы не хотел, чтобы весь текст из PDF-файла находился в одной строке, и, вероятно, использовал бы способность PDFTextStripper для более узкого указания, какой текст анализировать . Стоит также отметить, что хотя этот листинг кода получает PDF из Интернета ( Scala by Example PDF на http://www.scala-lang.org/docu/files/ScalaByExample.pdf ), существует множество конструкторов для PDDocument, которые позволяют для доступа к PDF-файлам в файловых системах и через другие типы потоков.

Разбор текста из онлайн PDF

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
/**
 * Parse text from an online PDF.
 */
private void parseOnlinePdfText()
{
   try
   {
      final URL scalaByExampleUrl = new URL(address);
      final PDDocument documentToBeParsed = PDDocument.load(scalaByExampleUrl.openStream());
      final PDFTextStripper stripper = new PDFTextStripper();
      final String pdfText = stripper.getText(documentToBeParsed);
      out.println("Parsed text size is " + pdfText.length() + " characters:");
      out.println(pdfText);
   }
   catch (IOException ioEx)
   {
      err.println("Exception while trying to parse text from PDF at " + address);
   }
}

Выпуск JDK 8

PDFBox 2 выявляет проблему в JDK 8, которая подана под ошибкой JDK-8041125 («Фильтр ColorConvertOp намного медленнее в JDK 8 по сравнению с JDK7»). Документация Apache PDFBox « Начало работы » описывает проблему: «Из-за изменения модуля управления цветом Java в сторону« LittleCMS »пользователи могут испытывать низкую производительность при работе с цветом». В этом же разделе «Начало работы» предлагается обходной путь: «отключите LittleCMS в пользу старой KCMS (системы управления цветом Kodak)».

Похоже, ошибка была идентифицирована и зарегистрирована IDR Solutions вместе с их коммерческой библиотекой Java PDF JPedal . Их запись в блоге Основные изменения в производительности Color в новых выпусках Java предоставляют более подробную информацию, связанную с этой проблемой.

Только что упомянутые публикации и документация, включая раздел «Начало работы» в Apache PDFBox 2, явно демонстрируют использование системных свойств Java для обхода проблемы путем явного указания использования KCMS (который может быть удален в любое время ) вместо значения по умолчанию. LittleCMS. Как утверждают эти источники, можно либо предоставить системное свойство для средства запуска Java [ java ] с параметром -D [ -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider ], либо указать свойство в исполняемом коде. сама [ System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider"); ].

Похоже, что эта проблема не относится только к версии 2 Apache PDFBox, но чаще встречается в Apache PDFBox 2, потому что версия 2 использует зависимые конструкции чаще и потому, что более вероятно, что кто-то, использующий Java 8, также использует более новый PDFBox.

Изменение в JDK 8 реализации по умолчанию, связанное со свойством sun.java2d.cmm демонстрирует точку, которую я пытался sun.java2d.cmm в своем недавнем сообщении в блоге « Наблюдения из истории обратной несовместимости Java» . В этом посте я заключил: «Остерегайтесь и осторожно используйте любые API, классы и инструменты, объявленные как экспериментальные или подлежащие удалению в будущих выпусках Java». Оказывается, что свойства системы Java 2D находятся в этом классе. Страница « Свойства системы для технологии Java 2D» предоставляет следующую справочную и предупреждающую информацию об использовании этих свойств:


В этом документе описано несколько неподдерживаемых свойств, которые можно использовать для настройки работы системы 2D-рисования. Вы можете использовать эти свойства для повышения производительности, исправления неправильного рендеринга или предотвращения сбоев системы при определенных конфигурациях.
Предупреждение: будьте осторожны при использовании этих свойств. Некоторые из них не поддерживаются по очень практическим причинам. … Поскольку эти свойства имеют единственную цель — включить или отключить поведение, зависящее от реализации, они могут быть изменены или удалены без уведомления. Некоторые свойства могут работать только в тех версиях продуктов, для которых они задокументированы.

Вывод

Apache PDFBox 2 — это относительно простой способ манипулирования PDF-документами в Java. Это либеральная лицензия Apache 2 делает ее доступной для очень большой аудитории, а ее открытый исходный код позволяет разработчикам увидеть, как использовать библиотеки, которые она использует под обложками, и адаптировать ее по мере необходимости.

Дополнительные ресурсы

Ссылка: Apache PDFBox 2 от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events .