วิธีทำงานกับเอกสาร PDF ใน C++

วิธีทำงานกับเอกสาร PDF ใน C++

Aspose.PDF FOSS for C++ คือไลบรารี C++20 ที่ใช้ใบอนุญาต MIT, ไม่พึ่งพาไลบรารีอื่น, สร้างและลิงก์ด้วย CMake — ไม่มีการนำเข้าโดยตัวจัดการแพ็กเกจให้เพิ่ม คู่มือฉบับนี้จะอธิบายขั้นตอนการทำงานหลักที่เน้น Document: เปิด PDF ที่มีอยู่, ตรวจสอบหน้าและเมตาดาต้า, ดึงข้อความ, และเรนเดอร์หน้าหนึ่งเป็นภาพ raster.

คู่มือแบบทีละขั้นตอน

ขั้นตอนที่ 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

ตรวจสอบว่า toolchain ทำงานได้โดยคอมไพล์โปรแกรมขนาดเล็กที่อ้างอิงกับหัวไฟล์:

#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 (1-indexed), สอดคล้องกับ semantics ของ 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().

ดูเพิ่มเติม

 ภาษาไทย