Skip to content

Primeiros passos com a PDF Oxide (Kotlin)

A PDF Oxide é a biblioteca PDF mais rápida para a JVM com extração de texto embutida — média de 0,8 ms e 100% de aprovação em 3.830 PDFs. O binding de Kotlin é uma fachada idiomática e pronta para Android sobre o binding de Java: ele adiciona use { } aos handles closable e converte os retornos Optional<T> do Java em T? nullable. Uma única biblioteca para extrair, criar e editar PDFs. Licença MIT, construída sobre um núcleo em Rust.

Instalação

Adicione o binding de Kotlin ao seu build.gradle.kts. Ele traz transitivamente o binding de Java, que é o dono da ponte nativa via JNI:

dependencies {
    implementation("fyi.oxide:pdf-oxide-kotlin:0.3.69")
}

Requisitos: JDK 17 ou superior. No Android, distribua a biblioteca nativa libpdf_oxide_jni.so em jniLibs/<abi>/; na JVM de desktop o loader a encontra automaticamente (use -Dfyi.oxide.pdf.lib.path=<path> para sobrescrever quando necessário).

Início Rápido

Gere um PDF a partir de Markdown, abra-o e leia o texto de volta. Os handles Pdf e PdfDocument são AutoCloseable, então envolva-os em use { }:

import fyi.oxide.pdf.Pdf
import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.producerOrNull

Pdf.fromMarkdown("# Hello pdf_oxide\n\nThis is a **Kotlin** binding.\n").use { pdf ->
    PdfDocument.open(pdf.save()).use { doc ->
        println("pages:    ${doc.pageCount()}")
        println("producer: ${doc.producerOrNull() ?: "(none)"}")
        println(doc.extractText(0))
    }
}

Pdf.fromMarkdown(String) retorna um builder Pdf closable; pdf.save() o serializa em um ByteArray. PdfDocument.open(ByteArray) abre esse conteúdo para leitura.

Abrindo um PDF

Abra um documento existente a partir de bytes e inspecione seus metadados. producerOrNull() e creatorOrNull() são as visões nullable de Kotlin sobre os getters Optional de Java:

import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.producerOrNull
import fyi.oxide.pdf.creatorOrNull

PdfDocument.open(pdfBytes).use { doc ->
    println("open:     ${doc.isOpen}")
    println("pages:    ${doc.pageCount()}")
    println("producer: ${doc.producerOrNull() ?: "(none)"}")
    println("creator:  ${doc.creatorOrNull() ?: "(none)"}")
}

Extração de texto

Extraia texto puro de qualquer página pelo seu índice (começando em zero) ou percorra todas as páginas:

import fyi.oxide.pdf.PdfDocument

PdfDocument.open(pdfBytes).use { doc ->
    // uma única página
    println(doc.extractText(0))

    // todas as páginas
    for (i in 0 until doc.pageCount()) {
        println("--- Page ${i + 1} ---")
        println(doc.extractText(i))
    }
}

Elementos da página

doc.page(i) retorna um PdfPage que expõe a geometria estruturada — palavras, linhas, caracteres, tabelas, imagens e anotações. Cada palavra carrega seu texto e uma bounding box:

import fyi.oxide.pdf.PdfDocument

PdfDocument.open(pdfBytes).use { doc ->
    val page = doc.page(0)
    println("size: ${page.width()} x ${page.height()}")

    page.words().take(8).forEach { word ->
        println("${word.text()} @ ${word.bbox()}")
    }

    println("lines:       ${page.lines().size}")
    println("chars:       ${page.chars().size}")
    println("tables:      ${page.tables().size}")
    println("images:      ${page.images().size}")
    println("annotations: ${page.annotations().size}")
}

A bbox() de uma palavra é um BBox com helpers como width() e height().

Conversão para Markdown e HTML

Converta o documento inteiro para Markdown ou renderize uma página em HTML:

import fyi.oxide.pdf.PdfDocument

PdfDocument.open(pdfBytes).use { doc ->
    val markdown = doc.toMarkdown()  // todas as páginas
    println(markdown)

    val html = doc.toHtml()
    println(html)
}

Busca

Busque por texto em todo o documento. Cada correspondência expõe seu texto via text():

import fyi.oxide.pdf.PdfDocument

PdfDocument.open(pdfBytes).use { doc ->
    val matches = doc.search("configuration")
    matches.forEach { m ->
        println("match: ${m.text()}")
    }
}

Extração automática

AutoExtractor roda o pipeline completo de extração em uma única chamada e retorna um AutoResult com o texto, além de renderizações opcionais em Markdown/HTML. As extensões markdownOrNull() / htmlOrNull() convertem os retornos Optional de Java em valores nullable:

import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.AutoExtractor
import fyi.oxide.pdf.markdownOrNull
import fyi.oxide.pdf.htmlOrNull

PdfDocument.open(pdfBytes).use { doc ->
    val result = AutoExtractor.of(doc).extractDocument()
    println(result.text())
    result.markdownOrNull()?.let { println(it) }
    result.htmlOrNull()?.let { println(it) }
}

Edição

DocumentEditor abre um PDF para edições estruturais — por exemplo, limpar os metadados antes de compartilhar — e então serializa o resultado de volta em bytes:

import fyi.oxide.pdf.DocumentEditor

DocumentEditor.open(pdfBytes).use { editor ->
    editor.scrubMetadata()
    val cleaned: ByteArray = editor.save()
    println("cleaned: ${cleaned.size} bytes")
}

Próximos passos