Начало работы с PDF Oxide (Java)
PDF Oxide — самая быстрая библиотека PDF для Java по извлечению текста: 0,8 мс в среднем и 100% успешных проходов на 3830 реальных PDF. Одно и то же ядро на Rust поставляется в Python, Go, JS и C#; биндинг для Java — это тонкий слой JNI с минимальной версией JDK 11 LTS и бесплатной совместимостью с Kotlin из того же JAR.
Установка
JAR содержит встроенные нативные библиотеки для Linux (x86_64/aarch64), macOS (x86_64/aarch64) и Windows (x86_64). Никакого компилятора или дополнительной настройки — нужная библиотека извлекается при первом вызове.
Maven
<dependency>
<groupId>fyi.oxide</groupId>
<artifactId>pdf-oxide</artifactId>
<version>0.3.69</version>
</dependency>
Gradle
// Kotlin DSL
implementation("fyi.oxide:pdf-oxide:0.3.69")
// Groovy
implementation 'fyi.oxide:pdf-oxide:0.3.69'
Быстрый старт
Откройте PDF и извлеките текст. PdfDocument реализует AutoCloseable, поэтому используйте try-with-resources, чтобы детерминированно освобождать нативный дескриптор.
import fyi.oxide.pdf.PdfDocument;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("report.pdf"))) {
System.out.println("Pages: " + doc.pageCount());
System.out.println(doc.extractText(0)); // zero-based page index
}
Можно открыть файл из строки с путём, объекта Path, массива byte[] или InputStream:
import fyi.oxide.pdf.PdfDocument;
byte[] pdfBytes = downloadFromS3();
try (PdfDocument doc = PdfDocument.open(pdfBytes)) {
String text = doc.extractText(0);
}
Извлечение текста
Пройдитесь по всем страницам по их индексу, начинающемуся с нуля:
import fyi.oxide.pdf.PdfDocument;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("book.pdf"))) {
for (int i = 0; i < doc.pageCount(); i++) {
System.out.println("--- Page " + (i + 1) + " ---");
System.out.println(doc.extractText(i));
}
}
Извлечение на уровне слов
PdfPage предоставляет структурированную геометрию. Метод words() возвращает список TextWord, где у каждого слова есть текст, ограничивающий прямоугольник и уверенность распознавания (OCR).
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.PdfPage;
import fyi.oxide.pdf.text.TextWord;
import fyi.oxide.pdf.geometry.BBox;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("paper.pdf"))) {
PdfPage page = doc.page(0);
for (TextWord word : page.words()) {
BBox b = word.bbox();
System.out.printf("'%s' at (%.1f, %.1f) conf=%.2f%n",
word.text(), b.x0(), b.y0(), word.confidence());
}
}
PdfPage также предоставляет lines(), chars(), tables(), images(), annotations(), а ещё width(), height() и text(BBox region) для извлечения из заданной области.
Преобразование в Markdown
Преобразуйте отдельную страницу или весь документ в Markdown с помощью вспомогательного класса MarkdownConverter (или удобных методов doc.toMarkdown(...)).
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.MarkdownConverter;
import java.nio.file.Files;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("report.pdf"))) {
String md = MarkdownConverter.toMarkdown(doc); // whole document
Files.writeString(Path.of("report.md"), md);
String pageMd = doc.toMarkdown(0); // single page
String pageHtml = doc.toHtml(0); // or HTML
}
Поиск
search() сканирует весь документ и возвращает список SearchMatch, где у каждого совпадения есть индекс страницы, ограничивающий прямоугольник и найденный текст.
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.search.SearchMatch;
import fyi.oxide.pdf.geometry.BBox;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("manual.pdf"))) {
for (SearchMatch m : doc.search("configuration")) {
BBox b = m.bbox();
System.out.printf("Page %d: '%s' at (%.0f, %.0f)%n",
m.pageIndex(), m.text(), b.x0(), b.y0());
}
}
Создание PDF
Тип Pdf создаёт PDF из Markdown, HTML или изображений. Он реализует AutoCloseable и не имеет страховки через Cleaner, поэтому всегда закрывайте его явно или через try-with-resources.
import fyi.oxide.pdf.Pdf;
import java.nio.file.Path;
try (Pdf pdf = Pdf.fromMarkdown("# Hello\n\nThis is a PDF.")) {
pdf.saveTo(Path.of("out.pdf"));
}
try (Pdf pdf = Pdf.fromHtml("<h1>Invoice</h1><p>Amount: $42</p>")) {
byte[] bytes = pdf.save(); // serialize to memory instead of disk
}
PDF, защищённые паролем
Передайте пароль в open() или вызовите authenticate() после перехвата PdfEncryptedException.
import fyi.oxide.pdf.PdfDocument;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("confidential.pdf"), "secret")) {
System.out.println(doc.extractText(0));
}
Обработка ошибок
PdfException extends RuntimeException (непроверяемое исключение) с типизированными подклассами и перечислением kind() для диспетчеризации в switch.
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.exception.PdfEncryptedException;
import fyi.oxide.pdf.exception.PdfException;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("document.pdf"))) {
String text = doc.extractText(0);
} catch (PdfEncryptedException e) {
System.err.println("Password required");
} catch (PdfException e) {
switch (e.kind()) {
case PARSE -> System.err.println("Malformed PDF");
case IO -> System.err.println("I/O error");
default -> System.err.println("PDF error: " + e.getMessage());
}
}
Kotlin
Тот же JAR работает напрямую из Kotlin — аксессоры record становятся свойствами.
import fyi.oxide.pdf.PdfDocument
import java.nio.file.Path
PdfDocument.open(Path.of("report.pdf")).use { doc ->
println("Pages: ${doc.pageCount()}")
println(doc.extractText(0))
}
Дальнейшие шаги
- Быстрый старт для Python – использование PDF Oxide из Python
- Быстрый старт для Rust – использование PDF Oxide из Rust
- Извлечение текста – подробные опции извлечения и рецепты
- Создание PDF – продвинутое создание, шифрование и метаданные