Як працювати з 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.gitadd_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().