Cách làm việc với tài liệu PDF trong C++
Aspose.PDF FOSS cho C++ là thư viện C++20 có giấy phép MIT, không phụ thuộc, được xây dựng và liên kết với CMake — không cần nhập qua trình quản lý gói. Hướng dẫn này đi qua quy trình cốt lõi tập trung vào Document: mở một tệp PDF hiện có, kiểm tra các trang và siêu dữ liệu, trích xuất văn bản, và render một trang thành hình ảnh raster.
Hướng dẫn từng bước
Bước 1: Cài đặt gói
Sao chép kho và thêm nó vào dự án CMake của bạn như một thư mục con:
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)Hoặc cấu hình và biên dịch nó độc lập:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildXác minh toolchain giải quyết bằng cách biên dịch một chương trình tối thiểu chống lại các header:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK - pages: " << doc.Pages().Count() << "\n";
}Một bản dựng thành công mà in pages: 0 cho Document mới tạo, trống xác nhận rằng thư viện đã được liên kết đúng cách.
Bước 2: Nhập các lớp cần thiết
#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>Bước 3: Mở tài liệu PDF và đếm số trang của nó
Xây dựng một Document từ đường dẫn tệp để mở một PDF hiện có. Document::Pages() trả về PageCollection, và Count() báo cáo số trang mà nó chứa:
Aspose::Pdf::Document doc("input.pdf");
std::cout << "Page count: " << doc.Pages().Count() << "\n";Bước 4: Đọc siêu dữ liệu tài liệu
Document::Info() trả về một đối tượng DocumentInfo với các bộ truy cập đọc/ghi có kiểu cho các mục từ điển chuẩn /Info:
auto& info = doc.Info();
std::cout << "Title: " << info.Title() << "\n";
std::cout << "Author: " << info.Author() << "\n";
std::cout << "Producer: " << info.Producer() << "\n";Bước 5: Trích xuất văn bản từ một trang
Aspose::Pdf::Text::TextAbsorber duyệt một Document hoặc một Page duy nhất và tích lũy văn bản mà nó gặp; Text() trả về kết quả sau đó. PageCollection được đánh số bắt đầu từ 1, vì vậy Pages()[1] là trang đầu tiên:
auto page = doc.Pages()[1];
Aspose::Pdf::Text::TextAbsorber absorber;
absorber.Visit(page);
std::cout << absorber.Text() << "\n";Visit() cũng chấp nhận toàn bộ Document trực tiếp (absorber.Visit(doc)) khi bạn muốn văn bản của mọi trang được nối liền với nhau thay vì một trang duy nhất.
Bước 6: Kết xuất Trang thành Hình ảnh Raster
BmpDevice kết xuất một Page thành ảnh BMP chưa nén. Hàm khởi tạo của nó nhận một Resolution để kiểm soát DPI đầu ra, và Process() ghi các byte đã kết xuất vào bất kỳ std::ostream nào:
Aspose::Pdf::Devices::BmpDevice device(Aspose::Pdf::Devices::Resolution(150));
std::ofstream imageOut("page1.bmp", std::ios::binary);
device.Process(page, imageOut);Bước 7: Cập nhật Siêu dữ liệu và Lưu Tài liệu
Các setter trên DocumentInfo chuẩn bị các thay đổi sẽ được đẩy khi Save() chạy lần tiếp theo trên Document sở hữu:
doc.Info().Title("Processed by Aspose.PDF FOSS for C++");
doc.Save("output.pdf");Các vấn đề thường gặp và cách khắc phục
Accessing Pages()[0] throws std::out_of_range
PageCollection được đánh số bắt đầu từ 1, phù hợp với semantics chuẩn Aspose.PDF — trang đầu tiên là Pages()[1]. Một chỉ số dưới 1 hoặc vượt quá Count() sẽ gây lỗi.
TextAbsorber::Text() trả về một chuỗi rỗng
Text() trả về bất kỳ dữ liệu nào đã được tích lũy bởi lời gọi Visit() gần nhất. Xác nhận Visit() thực sự đã được gọi trước khi đọc Text(), và trang hoặc tài liệu bạn truy cập chứa văn bản có thể trích xuất thay vì chỉ hình ảnh đã quét.
Tệp BMP đã render bất ngờ nhỏ hoặc trông trống
Giá trị Resolution thấp tạo ra một hình raster nhỏ. Tăng DPI truyền vào Resolution — ví dụ, Resolution(300) cho đầu ra chất lượng in — và xác nhận chỉ mục trang truyền vào Process() là chỉ mục bạn mong muốn.
DocumentInfo các trường được đọc lại là các chuỗi rỗng
Không phải mọi trình tạo PDF đều ghi các mục /Info tiêu chuẩn. Kiểm tra Producer() và Creator() để xem có giá trị trống không trước khi cho rằng việc trích xuất siêu dữ liệu đã thất bại — một chuỗi rỗng là kết quả được định nghĩa cho khóa không tồn tại.
Thay đổi được thực hiện bằng Info().Title(...) không xuất hiện trong tệp đã lưu
Các phép biến đổi DocumentInfo được đặt trong bộ nhớ và chỉ được lưu lại lần tiếp theo Save() chạy trên cùng một thể hiện Document. Đảm bảo việc chỉnh sửa siêu dữ liệu xảy ra trước Save(), không phải sau.
Câu hỏi thường gặp
Chỉ mục trang trong Aspose.PDF FOSS cho C++ là bắt đầu từ 0 hay từ 1?
Bắt đầu từ 1. doc.Pages()[1] luôn là trang đầu tiên.
Liệu TextAbsorber có thể trích xuất văn bản từ một trang duy nhất thay vì toàn bộ tài liệu không?
Có. Visit() được nạp chồng để chấp nhận hoặc một Document — trích xuất văn bản của mọi trang — hoặc một Page duy nhất, chỉ trích xuất văn bản của trang đó.
Tôi có cần gọi Save() nếu chỉ đọc dữ liệu từ tài liệu không?
Không. Save() chỉ cần thiết sau khi thực hiện các thay đổi cần ghi lại vào tệp, chẳng hạn như chỉnh sửa các trường DocumentInfo. Đọc số lượng trang, trích xuất văn bản, hoặc render một trang không làm thay đổi tài liệu.
Làm thế nào để tôi kiểm soát độ phân giải của một trang đã render?
Chuyển một giá trị Resolution vào hàm khởi tạo của thiết bị — ví dụ, Resolution(150) cho 150 DPI. Các giá trị cao hơn tạo ra các ảnh raster lớn hơn, độ trung thực cao hơn.
Định dạng nào BmpDevice tạo ra?
Một ảnh BMP không nén được ghi trực tiếp vào std::ostream được truyền cho Process().