مكتبة جافا بسيطة لمقارنة ملفين PDF. يتم عرض الملفات ومقارنتها بالبكسل. لا توجد مقارنة النص.
فقط قم بإدراجها كتبعية. يرجى التحقق من أحدث إصدار متاح:
< dependencies >
< dependency >
< groupId >de.redsix</ groupId >
< artifactId >pdfcompare</ artifactId >
< version >...</ version > <!-- see current version in the maven central tag above -->
</ dependency >
</ dependencies >
توجد واجهة مستخدم تفاعلية بسيطة، عند بدء تشغيل ملف jar دون أي وسائط إضافية (والتي تبدأ الفصل de.redsix.pdfcompare.Main). فهو يسمح لك باختيار الملفات للمقارنة وكذلك تحديد المناطق التي تريد تجاهلها وكتابتها في ملف التجاهل.
بجوار واجهة المستخدم، يمكنك توفير ملف متوقع وفعلي ومعلمة إضافية عبر واجهة سطر الأوامر (CLI). للحصول على مساعدة لواجهة سطر الأوامر، استخدم الخيار -h أو --help-.
usage: java -jar pdfcompare-x.x.x-full.jar [EXPECTED] [ACTUAL]
-h,--help Displays this text and exit
...
لكن تركيز PdfCompare ينصب على الاستخدام المضمن كمكتبة.
new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
سيؤدي هذا إلى إنتاج ملف PDF قد يتضمن علامات للاختلافات التي تم العثور عليها. يعرض PdfCompare صفحة من ملف pdf المتوقع ونفس الصفحة من ملف pdf الفعلي إلى صورة نقطية ويقارن هاتين الصورتين بالبكسل. وحدات البكسل المتساوية تتلاشى قليلاً. يتم تمييز وحدات البكسل المختلفة باللون الأحمر والأخضر. اللون الأخضر لوحدات البكسل الموجودة في ملف pdf المتوقع، ولكنها غير موجودة في ملف pdf الفعلي. اللون الأحمر لوحدات البكسل الموجودة في ملف pdf الفعلي، ولكنها لم تكن موجودة في ملف pdf المتوقع. وتوجد علامات على حافة الورقة باللون الأرجواني للعثور على المناطق التي تختلف بسرعة. يتم تمييز المناطق التي تم تجاهلها بخلفية صفراء. الصفحات التي كانت متوقعة، لكنها لم تصل، تم تمييزها بإطار أحمر. يتم تمييز الصفحات التي تظهر، ولكن لم تكن متوقعة، بحدود خضراء.
تقوم طريقة المقارنة بإرجاع CompareResult، والتي يمكن الاستعلام عنها:
final CompareResult result = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare ();
if ( result . isNotEqual ()) {
System . out . println ( "Differences found!" );
}
if ( result . isEqual ()) {
System . out . println ( "No Differences found!" );
}
if ( result . hasDifferenceInExclusion ()) {
System . out . println ( "Differences in excluded areas found!" );
}
result . getDifferences (); // returns page areas, where differences were found
للسهولة، تُرجع writeTo أيضًا حالة التساوي:
boolean isEquals = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
if (! isEquals ) {
System . out . println ( "Differences found!" );
}
يمكن استدعاء طريقة المقارنة بأسماء الملفات مثل Strings أو Files أو Paths أو InputStreams.
من الممكن أيضًا تحديد المناطق المستطيلة التي يتم تجاهلها أثناء المقارنة. للقيام بذلك، يجب إنشاء ملف يحدد المناطق التي يجب تجاهلها. تنسيق الملف هو JSON (أو في الواقع مجموعة شاملة تسمى HOCON) وله النموذج التالي:
exclusions: [
{
page : 2
x1 : 300 // entries without a unit are in pixels. Pdfs are rendered by default at 300DPI
y1 : 1000
x2 : 550
y2 : 1300
} ,
{
// page is optional. When not given, the exclusion applies to all pages.
x1 : 130.5 mm // entries can also be given in units of cm, mm or pt (DTP-Point defined as 1/72 Inches)
y1 : 3.3 cm
x2 : 190 mm
y2 : 3.7 cm
} ,
{
page : 7
// coordinates are optional. When not given, the whole page is excluded.
}
]
عندما لا يتم العثور على ملف الاستثناء المقدم، يتم تجاهله ويتم إجراء المقارنة بدون الاستثناءات.
يتم توفير الاستثناءات في الكود على النحو التالي:
new PdfComparator ( "expected.pdf" , "actual.pdf" ). withIgnore ( "ignore.conf" ). compare ();
وبدلاً من ذلك، يمكن إضافة الاستثناء عبر واجهة برمجة التطبيقات (API) على النحو التالي:
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withIgnore ( new PageArea ( 1 , 230 , 350 , 450 , 420 ))
. withIgnore ( new PageArea ( 2 ))
. compare ();
عندما تريد مقارنة ملفات PDF المحمية بكلمة مرور، يمكنك إعطاء كلمة المرور إلى المقارنة من خلال أساليب withExpectedPassword (كلمة مرور السلسلة) أو withActualPassword (كلمة مرور السلسلة) على التوالي.
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withExpectedPassword ( "somePwd" )
. withActualPassword ( "anotherPwd" )
. compare ();
يمكن تكوين PdfCompare باستخدام ملف التكوين. يُسمى ملف التكوين الافتراضي "application.conf" ويجب أن يكون موجودًا في جذر مسار الفصل.
يستخدم PdfCompare Lightbend Config (المعروف سابقًا باسم TypeSafe Config) لقراءة ملفات التكوين الخاصة به. إذا كنت تريد تحديد ملف تكوين آخر، فيمكنك معرفة المزيد حول ذلك هنا: https://github.com/lightbend/config#standard-behavior. على وجه الخصوص، يمكنك تحديد ملف تكوين بديل باستخدام وسيطة سطر الأوامر -Dconfig.file=path/to/file.
وبدلاً من ذلك، يمكنك تحديد المعلمات إما من خلال متغيرات بيئة النظام أو كمعلمة Jvm باستخدام -DvariableName=
هناك طريقة أخرى لتحديد موقع تكوين مختلف برمجيًا وهي إنشاء ConfigFileEnvironment(...) جديد وتمريره إلى PdfCompare.withEnvironment(...).
جميع الإعدادات التي يمكن تغييرها من خلال ملف application.conf يمكن أيضًا تغييرها برمجيًا من خلال واجهة برمجة التطبيقات. للقيام بذلك يمكنك استخدام الكود التالي:
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withEnvironment ( new SimpleEnvironment ()
. setActualColor ( Color . green )
. setExpectedColor ( Color . blue ))
. compare ();
يقوم SimpleEnvironment بتفويض كافة الإعدادات، التي لم يتم تعيينها، إلى البيئة الافتراضية.
من خلال البيئة يمكنك ضبط إعدادات الذاكرة (انظر أعلاه) والإعدادات التالية:
ديسيبل متوحد الخواص = 300
يضبط DPI التي يتم عرض صفحات Pdf بها. الافتراضي هو 300.
اللون المتوقع = 00B400 (أخضر)
اللون المتوقع هو اللون المستخدم لوحدات البكسل المتوقعة، ولكنها غير موجودة. يتم تحديد الألوان بتنسيق HTML-Stlye (بدون بادئة "#"): يحدد أول حرفين الجزء الأحمر من اللون بالنظام الست عشري. يحدد الحرفان التاليان الجزء الأخضر من اللون. يحدد الحرفان الأخيران الجزء الأزرق من اللون المطلوب استخدامه.
اللون الفعلي=D20000 (أحمر)
اللون الفعلي هو اللون المستخدم لوحدات البكسل الموجودة، ولكن لم تكن متوقعة. يتم تحديد الألوان بتنسيق HTML-Stlye (بدون بادئة "#"): يحدد أول حرفين الجزء الأحمر من اللون بالنظام الست عشري. يحدد الحرفان التاليان الجزء الأخضر من اللون. يحدد الحرفان الأخيران الجزء الأزرق من اللون المطلوب استخدامه.
tempDir=System.property("java.io.tmpdir")
يضبط الدليل حيث يتم كتابة الملفات المؤقتة. الإعدادات الافتراضية لـ java لـ java.io.tmpdir، والتي عادةً ما تحدد افتراضيًا خاصًا بالنظام، مثل /tmp في معظم أنظمة يونكس.
المسموح بهDifferenceInPercentPerPage=0.2
النسبة المئوية لوحدات البكسل التي قد تختلف لكل صفحة. الافتراضي هو 0. إذا كان العرض الخاص بك متوقفًا قليلاً لسبب ما أو سمحت ببعض هامش الخطأ، فيمكنك تكوين نسبة مئوية من وحدات البكسل التي يتم تجاهلها أثناء المقارنة. وبهذه الطريقة، يتم الإبلاغ عن الاختلاف فقط عندما يكون الاختلاف أكبر من النسبة المئوية المحددة لوحدات البكسل. يتم حساب النسبة لكل صفحة. لا يعني ذلك أن الاختلافات لا تزال محددة في ملف الإخراج، عند إضافةEqualPagesToResult.
معالجة متوازية = صحيح
عند التعيين على خطأ، يتم تعطيل كافة عمليات المعالجة المتوازية ومعالجة كل شيء في سلسلة رسائل واحدة.
addEqualPagesToResult=true
عند التعيين على خطأ، تتم إضافة الصفحات التي بها اختلافات فقط إلى النتيجة وهذا هو مستند PDF الخاص بالاختلاف الناتج.
FailOnMissingIgnoreFile=false
عند التعيين على "صحيح"، يؤدي ملف التجاهل المفقود إلى استثناء. وإلا فسيتم تجاهله وتتم كتابة رسائل سجل مستوى المعلومات فقط.
هناك عدد قليل من التطبيقات المختلفة لـ CompareResults بخصائص مختلفة. ويمكن استخدامه للتحكم في جوانب معينة من سلوك النظام، وخاصة استهلاك الذاكرة.
من الجيد معرفة بعض التفاصيل الداخلية عند استخدام PdfCompare. إليك باختصار ما يفعله PdfCompare، عندما يقارن بين ملفين PDF.
يستخدم PdfCompare مكتبة Apache PdfBox لقراءة وكتابة ملفات Pdf.
لذا فإن مقارنة ملفات Pdf الكبيرة يمكن أن تستهلك قدرًا كبيرًا من الذاكرة. لم أجد حتى الآن طريقة لكتابة الفرق بين صفحة Pdf وصفحة بشكل متزايد باستخدام PdfBox، ولكن هناك بعض الحلول.
يوجد حاليًا نتيجتان مختلفتان للمقارنة، لهما استراتيجيات مختلفة لتبديل الصفحات إلى القرص وبالتالي الحد من استهلاك الذاكرة.
يمكن استخدام تطبيق CompareResult مختلفًا على النحو التالي:
new PdfComparator ( "expected.pdf" , "actual.pdf" , new CompareResultWithPageOverflow ()). compare ();
هناك أيضًا بعض الإعدادات الداخلية لحدود الذاكرة التي يمكن تغييرها. ما عليك سوى إضافة ملف يسمى "application.conf" إلى جذر مسار الفصل. يمكن أن يحتوي هذا الملف على بعض أو كل الإعدادات التالية لاستبدال الإعدادات الافتراضية الواردة هنا:
imageCacheSizeCount=30
كم عدد الصور المخزنة مؤقتًا بواسطة PdfBox
maxImageSizeInCache=100000
الحد الأقصى التقريبي لحجم الصور المخزنة مؤقتًا، لمنع تخزين الصور الكبيرة جدًا مؤقتًا
mergeCacheSizeMB=100
عندما تتم كتابة ملفات Pdf جزئيًا ودمجها لاحقًا، فهذه هي ذاكرة التخزين المؤقت للذاكرة التي تم تكوينها لمثيل PdfBox الذي يقوم بالدمج.
SwapCacheSizeMB=100
عندما تتم كتابة ملفات Pdf جزئيًا، فهذه هي ذاكرة التخزين المؤقت للذاكرة التي تم تكوينها لمثيل PdfBox الذي يقوم بالكتابة الجزئية.
documentCacheSizeMB=200
هذا هو حجم ذاكرة التخزين المؤقت التي تم تكوينها لمثيل PdfBox، الذي يقوم بتحميل المستندات التي تتم مقارنتها.
معالجة متوازية = صحيح
عند التعيين على خطأ، يتم تعطيل كافة عمليات المعالجة المتوازية ومعالجة كل شيء في سلسلة رسائل واحدة.
إجمالي TimeoutInMinutes = 15
ضبط المهلة الشاملة. يعد هذا إجراءً أمنيًا للكشف عن حالات الجمود المحتملة. قد تستغرق المقارنات المعقدة وقتًا أطول، لذا قد يلزم زيادة هذه القيمة.
executorTimeoutInSeconds=60
يضبط المهلة لانتظار انتهاء المنفذين بعد الوصول إلى المهلة الإجمالية. من غير المرجح أن تحتاج إلى تغيير هذا.
لذا، في هذا التكوين الافتراضي، يجب أن يستخدم PdfBox ما يصل إلى 400 ميجابايت من ذاكرة الوصول العشوائي لذاكرة التخزين المؤقت الخاصة به، قبل التبديل إلى القرص. لدي خبرة جيدة في منح مساحة كومة تبلغ 2 جيجابايت لـ JVM.
شكرًا جزيلاً لـ Chethan Rao [email protected] لمساعدتي في تشخيص مشاكل نفاد الذاكرة وتقديم فكرة الكتابة الجزئية ودمج ملفات PDF التي تم إنشاؤها.