كيفية العمل مع مستندات PDF في C++
Aspose.PDF FOSS للـ C++ هو مكتبة C++20 مرخصة MIT وخالية من التبعيات، تم بناؤها وربطها باستخدام 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: تحديث البيانات الوصفية وحفظ المستند
تُجري الدوال setter في 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().