Skip to content

Перші кроки з PDF Oxide (Swift)

PDF Oxide — найшвидша бібліотека для PDF із вбудованим витяганням тексту: середній час 0.8 мс і 100% успішних результатів на 3830 PDF. Прив’язка для Swift, що з’явилася у v0.3.69, обгортає ядро на Rust через C ABI: дескрипторами володіють класи (звільняються в deinit), C-буфери копіюються у Swift-типи String/[UInt8], а коди помилок викидаються як PdfOxideError.

Встановлення

Прив’язка лінкується з cdylib зі стандартним набором функцій. Зберіть нативну бібліотеку, а потім вкажіть SwiftPM шлях до заголовків і бібліотеки:

# 1. build the native library (shipped binding feature set)
cargo build --release --lib --features ocr,rendering,signatures,barcodes,tsa-client,system-fonts

# 2. test + run the example (Package.swift reads PDF_OXIDE_INCLUDE_DIR / _LIB_DIR)
cd swift
export PDF_OXIDE_INCLUDE_DIR="$PWD/../include"
export PDF_OXIDE_LIB_DIR="$PWD/../target/release"
DYLD_LIBRARY_PATH="$PDF_OXIDE_LIB_DIR" swift test
DYLD_LIBRARY_PATH="$PDF_OXIDE_LIB_DIR" swift run basic_extraction

Швидкий старт

Зберіть PDF із Markdown, відкрийте його з отриманих байтів і витягніть текст. Увесь цикл виконується без жодного зовнішнього файлу:

import PdfOxide

let pdf = try Pdf.fromMarkdown("# Hello pdf_oxide\n\nThis is a **Swift** binding.\n")
let doc = try Document.openFromBytes(try pdf.toBytes())

print("pages:   \(try doc.pageCount())")
print("version: \(try doc.version())")
print(try doc.extractText(0))

Щоб відкрити файл із диска, використовуйте Document.open(_:):

import PdfOxide

let doc = try Document.open("research-paper.pdf")
print("Pages:   \(try doc.pageCount())")
print("Version: \(try doc.version())")        // e.g. 1.7

Витягання тексту

extractText(_:) повертає текст однієї сторінки (нумерація з нуля). Пройдіться циклом по pageCount(), щоб прочитати весь документ:

import PdfOxide

let doc = try Document.open("book.pdf")
for i in 0..<(try doc.pageCount()) {
    print("--- Page \(i + 1) ---")
    print(try doc.extractText(i))
}

toPlainText(_:) дає спрощений варіант без розмітки, а методи *All() витягають усі сторінки за один виклик:

let doc = try Document.open("report.pdf")
let plain = try doc.toPlainText(0)            // single page, no layout
let everything = try doc.toPlainTextAll()     // all pages concatenated

Слова та символи

extractWords(_:) повертає [Word] з обмежувальним прямокутником і метаданими шрифту для кожного слова. extractChars(_:) повертає [Char] з позиціонуванням окремих символів:

import PdfOxide

let doc = try Document.open("paper.pdf")

let words = try doc.extractWords(0)
for word in words.prefix(10) {
    print("'\(word.text)' at (\(word.bbox.x), \(word.bbox.y)) "
        + "font=\(word.fontName) size=\(word.fontSize) bold=\(word.bold)")
}

let chars = try doc.extractChars(0)
for ch in chars.prefix(10) {
    let scalar = Unicode.Scalar(ch.character).map(String.init) ?? "?"
    print("'\(scalar)' size=\(ch.fontSize) font=\(ch.fontName)")
}

Поля Word: text (String), bbox (Bbox), fontName (String), fontSize (Double), bold (Bool). Поля Char: character (UInt32, кодова точка), bbox, fontName, fontSize. Bbox надає x, y, width і height як Double.

Текст також можна отримувати рядок за рядком за допомогою extractTextLines(_:), який повертає [TextLine] (text, bbox, wordCount):

let lines = try doc.extractTextLines(0)
for line in lines {
    print("\(line.wordCount) words: \(line.text)")
}

Конвертація у Markdown та HTML

Конвертуйте окрему сторінку або весь документ у Markdown чи HTML:

import PdfOxide

let doc = try Document.open("paper.pdf")

let md = try doc.toMarkdown(0)        // one page to Markdown
let mdAll = try doc.toMarkdownAll()   // whole document to Markdown
let html = try doc.toHtml(0)          // one page to HTML
let htmlAll = try doc.toHtmlAll()     // whole document to HTML

print(mdAll)

Пошук

search(_:_:_:) шукає на окремій сторінці; searchAll(_:_:) шукає по всьому документу. Обидва приймають пошуковий запит і прапорець caseSensitive, повертаючи [SearchResult] (text, page, bbox):

import PdfOxide

let doc = try Document.open("manual.pdf")

// Search a single page (page 0, case-insensitive)
let hits = try doc.search(0, "configuration", false)
for hit in hits {
    print("page \(hit.page): '\(hit.text)' at (\(hit.bbox.x), \(hit.bbox.y))")
}

// Search the whole document
let allHits = try doc.searchAll("configuration", false)
print("\(allHits.count) total matches")

Створення PDF

Тип Pdf надає фабричні методи, які будують документ із вихідного формату. Збережіть його на диск за допомогою save(_:) або отримайте сирі байти через toBytes():

import PdfOxide

try Pdf.fromMarkdown("# Hello World\n\nThis is a PDF.").save("output.pdf")
try Pdf.fromHtml("<h1>Invoice</h1><p>Amount: $42</p>").save("invoice.pdf")
try Pdf.fromText("Plain text content.").save("notes.pdf")

let bytes = try Pdf.fromMarkdown("# In-memory\n\nbody\n").toBytes()
print("produced \(bytes.count) bytes")

Обробка помилок

Кожен виклик, що може завершитися невдало, викидає PdfOxideError, який містить назву операції, що не вдалася, і відповідний код помилки C ABI:

import PdfOxide

do {
    let doc = try Document.open("document.pdf")
    print(try doc.extractText(0))
} catch let error as PdfOxideError {
    print("PDF error: \(error)")   // e.g. "PdfOxideError: open failed (error code 1)"
}

Наступні кроки