Jak pracować z dokumentami PDF w C++

Jak pracować z dokumentami PDF w C++

Aspose.PDF FOSS for C++ jest biblioteką na licencji MIT, wolną od zależności, napisaną w C++20, budowaną i linkowaną przy użyciu CMake — nie ma potrzeby importowania z menedżera pakietów. Ten przewodnik przechodzi przez główny przepływ pracy skoncentrowany na Document: otwórz istniejący PDF, przejrzyj jego strony i metadane, wyodrębnij tekst i wyrenderuj stronę jako obraz rastrowy.

Przewodnik krok po kroku

Krok 1: Zainstaluj pakiet

Sklonuj repozytorium i dodaj je do swojego projektu CMake jako podkatalog:

git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Cpp.git
add_subdirectory(Aspose.PDF-FOSS-for-Cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)

Lub skonfiguruj i zbuduj go jako samodzielny projekt:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

Sprawdź, czy toolchain się rozwiązuje, kompilując minimalny program z użyciem nagłówków:

#include <aspose/pdf/document.hpp>
#include <iostream>

int main() {
    Aspose::Pdf::Document doc;
    std::cout << "Linked OK - pages: " << doc.Pages().Count() << "\n";
}

Udany build, który wypisuje pages: 0 dla nowo utworzonego, pustego Document, potwierdza, że biblioteka została poprawnie połączona.


Krok 2: Zaimportuj wymagane klasy

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>
#include <aspose/pdf/page.hpp>
#include <aspose/pdf/page_collection.hpp>
#include <aspose/pdf/text_absorber.hpp>
#include <aspose/pdf/bmp_device.hpp>
#include <aspose/pdf/resolution.hpp>
#include <fstream>
#include <iostream>

Krok 3: Otwórz dokument PDF i policz jego strony

Utwórz Document z ścieżki pliku, aby otworzyć istniejący PDF. Document::Pages() zwraca PageCollection, a Count() podaje, ile stron zawiera:

Aspose::Pdf::Document doc("input.pdf");
std::cout << "Page count: " << doc.Pages().Count() << "\n";

Krok 4: Odczytaj metadane dokumentu

Document::Info() zwraca obiekt DocumentInfo z typowanymi akcesorami odczytu/zapisu dla standardowych wpisów słownika /Info:

auto& info = doc.Info();
std::cout << "Title: "    << info.Title()    << "\n";
std::cout << "Author: "   << info.Author()   << "\n";
std::cout << "Producer: " << info.Producer() << "\n";

Krok 5: Wyodrębnij tekst ze strony

Aspose::Pdf::Text::TextAbsorber przegląda Document lub pojedynczy Page i gromadzi napotkany tekst; Text() zwraca wynik później. PageCollection jest indeksowane od 1, więc Pages()[1] jest pierwszą stroną:

auto page = doc.Pages()[1];

Aspose::Pdf::Text::TextAbsorber absorber;
absorber.Visit(page);
std::cout << absorber.Text() << "\n";

Visit() akceptuje również cały Document bezpośrednio (absorber.Visit(doc)), gdy chcesz, aby tekst wszystkich stron był połączony razem zamiast jednej strony.


Krok 6: Renderowanie strony do obrazu rastrowego

BmpDevice renderuje Page do nieskompresowanego obrazu BMP. Jego konstruktor przyjmuje Resolution, który kontroluje wyjściową DPI, a Process() zapisuje wyrenderowane bajty do dowolnego std::ostream:

Aspose::Pdf::Devices::BmpDevice device(Aspose::Pdf::Devices::Resolution(150));

std::ofstream imageOut("page1.bmp", std::ios::binary);
device.Process(page, imageOut);

Krok 7: Aktualizacja metadanych i zapis dokumentu

Settery w DocumentInfo przygotowują zmiany, które są wypychane przy następnym uruchomieniu Save() na należącym Document:

doc.Info().Title("Processed by Aspose.PDF FOSS for C++");
doc.Save("output.pdf");

Typowe problemy i rozwiązania

Accessing Pages()[0] throws std::out_of_range

PageCollection jest indeksowane od 1, zgodnie z kanoniczną semantyką Aspose.PDF — pierwsza strona to Pages()[1]. Indeks poniżej 1 lub powyżej Count() powoduje błąd.

TextAbsorber::Text() zwraca pusty ciąg znaków

Text() zwraca to, co zostało zebrane podczas ostatniego wywołania Visit(). Upewnij się, że Visit() został rzeczywiście wywołany przed odczytaniem Text(), oraz że strona lub dokument, który otworzyłeś, zawiera tekst możliwy do wyodrębnienia, a nie jedynie zeskanowane obrazy.

Renderowany plik BMP jest nieoczekiwanie mały lub wygląda na pusty

Niska wartość Resolution powoduje mały obraz rastrowy. Zwiększ DPI przekazywane do Resolution — na przykład Resolution(300) dla wydruku w jakości drukarskiej — i upewnij się, że indeks strony przekazany do Process() jest tym, którego oczekiwałeś.

DocumentInfo pola odczytywane jako puste ciągi znaków

Nie każdy twórca PDF zapisuje standardowe wpisy /Info. Sprawdź Producer() i Creator() pod kątem pustych wartości, zanim założysz, że wyodrębnianie metadanych nie powiodło się — pusty ciąg znaków jest zdefiniowanym wynikiem dla nieobecnego klucza.

Zmiany wprowadzone przy użyciu Info().Title(...) nie pojawiają się w zapisanym pliku

Mutacje DocumentInfo są przygotowywane w pamięci i zapisywane dopiero przy następnym uruchomieniu Save() na tej samej instancji Document. Upewnij się, że edycja metadanych odbywa się przed Save(), a nie po.

Najczęściej zadawane pytania

Czy indeksowanie stron w Aspose.PDF FOSS dla C++ jest zerowe czy jedynkowe?

Jedynkowe. doc.Pages()[1] jest zawsze pierwszą stroną.

Czy TextAbsorber może wyodrębnić tekst z jednej strony zamiast z całego dokumentu?

Tak. Visit() jest przeciążone, aby przyjmować albo Document — który wyodrębnia tekst ze wszystkich stron — albo pojedynczy Page, który wyodrębnia tekst tylko z tej strony.

Czy muszę wywołać Save(), jeśli tylko odczytuję dane z dokumentu?

Nie. Save() jest wymagane tylko po wprowadzeniu zmian, które muszą zostać zapisane do pliku, takich jak edycja pól DocumentInfo. Odczytywanie liczby stron, wyodrębnianie tekstu czy renderowanie strony nie modyfikuje dokumentu.

Jak kontrolować rozdzielczość renderowanej strony?

Przekaż wartość Resolution do konstruktora urządzenia — na przykład Resolution(150) dla 150 DPI. Wyższe wartości generują większe, bardziej wierne obrazy rastrowe.

Jaki format generuje BmpDevice?

Nieskompresowany obraz BMP zapisywany bezpośrednio do std::ostream przekazanego do Process().

Zobacz także

 Polski