Як працювати з PDF-документами в C++

Як працювати з PDF-документами в C++

Aspose.PDF FOSS for C++ — це бібліотека з ліцензією MIT, без залежностей, C++20, зібрана та підключена за допомогою CMake — не потрібно додавати імпорт через менеджер пакетів. Цей посібник проходить через основний робочий процес, орієнтований на Document: відкриття існуючого PDF, перегляд його сторінок та метаданих, видобуток тексту та рендеринг сторінки у растрове зображення.

Покроковий посібник

Крок 1: Встановити пакет

Клонуйте репозиторій і додайте його у ваш CMake-проект як піддиректорію:

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)

Або налаштуйте та збирайте його окремо:

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

Перевірте, що інструментальний ланцюжок працює, скомпілювавши мінімальну програму проти заголовків:

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

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

Успішна збірка, яка виводить pages: 0 для щойно створеного, порожнього Document, підтверджує, що бібліотека правильно пов’язана.


Крок 2: Імпорт необхідних класів

#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>

Крок 3: Відкрити PDF-документ і підрахувати його сторінки

Створіть Document за шляхом до файлу, щоб відкрити існуючий PDF. Document::Pages() повертає PageCollection, а Count() повідомляє, скільки сторінок він містить:

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

Крок 4: Читання метаданих документа

Document::Info() повертає об’єкт DocumentInfo з типізованими аксесорами читання/запису для стандартних записів словника /Info:

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

Крок 5: Видобути текст зі сторінки

Aspose::Pdf::Text::TextAbsorber проходить Document або окремий Page і накопичує виявлений текст; Text() повертає результат після цього. PageCollection індексується з 1, тому Pages()[1] — це перша сторінка:

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

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

Visit() також приймає весь Document безпосередньо (absorber.Visit(doc)), коли ви хочете, щоб текст усіх сторінок був об’єднаний разом замість окремої сторінки.


Крок 6: Візуалізувати сторінку у растрове зображення

BmpDevice перетворює Page у незапаковане BMP-зображення. Його конструктор приймає Resolution, який контролює вихідний DPI, а Process() записує відрендерені байти у будь-який std::ostream:

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

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

Крок 7: Оновити метадані та зберегти документ

Сетери в DocumentInfo підготовлюють зміни, які будуть застосовані під час наступного запуску Save() на власнику Document:

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

Поширені проблеми та їх вирішення

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

PageCollection індексований з 1, відповідаючи канонічній семантиці Aspose.PDF — перша сторінка це Pages()[1]. Індекс менший за 1 або більший за Count() викликає помилку.

TextAbsorber::Text() повертає порожній рядок

Text() повертає те, що було накопичено під час останнього виклику Visit(). Переконайтеся, що Visit() дійсно був викликаний перед читанням Text(), і що сторінка або документ, який ви відкрили, містить витягуваний текст, а не лише скановані зображення.

Згенерований BMP-файл несподівано малий або виглядає порожнім

Низьке значення Resolution створює маленьке растрове зображення. Збільшіть DPI, що передається до Resolution — наприклад, Resolution(300) для виводу високої якості — і переконайтеся, що індекс сторінки, переданий до Process(), є тим, який ви мали на увазі.

DocumentInfo поля читаються як порожні рядки

Не кожен виробник PDF записує стандартні записи /Info. Перевірте Producer() і Creator() на наявність порожніх значень, перш ніж припускати, що витяг метаданих не вдався — порожній рядок є визначеним результатом для відсутнього ключа.

Зміни, внесені за допомогою Info().Title(...) не з’являються у збереженому файлі

DocumentInfo мутації накопичуються в пам’яті і зберігаються лише під час наступного запуску Save() на тому самому екземплярі Document. Переконайтеся, що редагування метаданих відбувається до Save(), а не після.

Поширені запитання

Чи індексація сторінок у Aspose.PDF FOSS для C++ починається з нуля чи з одиниці?

З індексом з одиниці. doc.Pages()[1] завжди є першою сторінкою.

Чи може TextAbsorber витягти текст лише з однієї сторінки, а не з усього документа?

Так. Visit() перевантажений і приймає або Document — який витягує текст усіх сторінок —, або одну Page, яка витягує лише текст цієї сторінки.

Чи потрібно викликати Save(), якщо я лише читаю дані з документа?

Ні. Save() потрібен лише після змін, які потрібно записати у файл, наприклад редагування полів DocumentInfo. Читання кількості сторінок, витяг тексту або рендеринг сторінки не модифікує документ.

Як я можу керувати роздільною здатністю відрендереної сторінки?

Передайте значення Resolution конструктору пристрою — наприклад, Resolution(150) для 150 DPI. Вищі значення створюють більші растрові зображення більш високої точності.

Який формат створює BmpDevice?

Некомпресоване BMP-зображення, записане безпосередньо у std::ostream, передане до Process().

Дивіться також

 Українська