ไลบรารี Java อย่างง่ายสำหรับเปรียบเทียบไฟล์ PDF สองไฟล์ ไฟล์ถูกเรนเดอร์และเปรียบเทียบพิกเซลต่อพิกเซล ไม่มีการเปรียบเทียบข้อความ
เพียงรวมไว้เป็นการพึ่งพา โปรดตรวจสอบเวอร์ชันล่าสุดที่มีอยู่:
< dependencies >
< dependency >
< groupId >de.redsix</ groupId >
< artifactId >pdfcompare</ artifactId >
< version >...</ version > <!-- see current version in the maven central tag above -->
</ dependency >
</ dependencies >
มี UI แบบโต้ตอบที่เรียบง่าย เมื่อคุณเริ่มไฟล์ jar โดยไม่มีข้อโต้แย้งเพิ่มเติม (ซึ่งเริ่มคลาส de.redsix.pdfcompare.Main) ช่วยให้คุณสามารถเลือกไฟล์ที่จะเปรียบเทียบและทำเครื่องหมายพื้นที่ที่จะละเว้นและเขียนไฟล์เหล่านั้นลงในไฟล์ละเว้น
ถัดจาก UI คุณสามารถจัดเตรียมไฟล์ที่คาดหวังและไฟล์จริง รวมถึงพารามิเตอร์เพิ่มเติมผ่าน CLI หากต้องการรับความช่วยเหลือสำหรับ 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 แสดงผลเพจจาก Expected.pdf และหน้าเดียวกันจาก realme.pdf ไปเป็นรูปภาพบิตแมป และเปรียบเทียบรูปภาพทั้งสองนี้แบบพิกเซลต่อพิกเซล พิกเซลที่เท่ากันจะจางลงเล็กน้อย พิกเซลที่แตกต่างกันจะถูกทำเครื่องหมายด้วยสีแดงและสีเขียว สีเขียวสำหรับพิกเซลที่อยู่ในสิ่งที่คาดหวัง.pdf แต่ไม่มีอยู่ในไฟล์ที่เกิดขึ้นจริง สีแดงสำหรับพิกเซลที่มีอยู่ในactual.pdfแต่ไม่อยู่ในexpected.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 ที่ป้องกันด้วยรหัสผ่าน คุณสามารถมอบรหัสผ่านให้กับ Comparator ผ่านเมธอด withExpectedPassword(Stringpassword) หรือ withActualPassword(Stringpassword) ตามลำดับ
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withExpectedPassword ( "somePwd" )
. withActualPassword ( "anotherPwd" )
. compare ();
PdfCompare สามารถกำหนดค่าได้ด้วยไฟล์กำหนดค่า ไฟล์กำหนดค่าเริ่มต้นเรียกว่า "application.conf" และจะต้องอยู่ในรากของ classpath
PdfCompare ใช้ Lightbend Config (ก่อนหน้านี้เรียกว่า TypeSafe Config) เพื่ออ่านไฟล์การกำหนดค่า หากคุณต้องการระบุไฟล์การกำหนดค่าอื่น คุณสามารถดูข้อมูลเพิ่มเติมได้ที่นี่: https://github.com/lightbend/config#standard-behavior โดยเฉพาะอย่างยิ่ง คุณสามารถระบุไฟล์กำหนดค่าการแทนที่ด้วยอาร์กิวเมนต์บรรทัดคำสั่ง -Dconfig.file=path/to/file
หรือคุณสามารถระบุพารามิเตอร์ผ่านตัวแปรสภาพแวดล้อมระบบหรือเป็นพารามิเตอร์ Jvm ด้วย -DvariableName=
อีกวิธีหนึ่งในการระบุตำแหน่งการกำหนดค่าอื่นโดยทางโปรแกรมคือการสร้าง ConfigFileEnvironment(...) ใหม่และส่งผ่านไปยัง PdfCompare.withEnvironment(...)
การตั้งค่าทั้งหมดที่สามารถเปลี่ยนแปลงได้ผ่านไฟล์ application.conf ยังสามารถเปลี่ยนแปลงโดยทางโปรแกรมผ่าน API ได้อีกด้วย โดยคุณสามารถใช้รหัสต่อไปนี้:
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
การประมวลผลแบบขนาน = true
เมื่อตั้งค่าเป็นเท็จ จะปิดใช้งานการประมวลผลแบบขนานทั้งหมดและประมวลผลทุกอย่างในเธรดเดียว
addEqualPagesToResult=true
เมื่อตั้งค่าเป็นเท็จ เฉพาะหน้าที่มีความแตกต่างเท่านั้นที่จะถูกเพิ่มเข้าไปในผลลัพธ์ และนี่คือผลลัพธ์ของเอกสาร PDF ที่แตกต่างกัน
failedOnMissingIgnoreFile=false
เมื่อตั้งค่าเป็นจริง ไฟล์ละเว้นที่หายไปจะนำไปสู่ข้อยกเว้น มิฉะนั้นจะถูกละเว้นและเขียนเฉพาะข้อความบันทึกระดับข้อมูลเท่านั้น
มีการใช้งาน CompareResults ที่แตกต่างกันสองสามรายการพร้อมคุณสมบัติที่แตกต่างกัน สามารถใช้เพื่อควบคุมลักษณะการทำงานของระบบบางประการ โดยเฉพาะอย่างยิ่งการใช้หน่วยความจำ
เป็นการดีที่จะทราบข้อมูลภายในบางประการ เมื่อใช้ PdfCompare โดยสรุปสิ่งที่ PdfCompare ทำเมื่อเปรียบเทียบ PDF สองไฟล์
PdfCompare ใช้ไลบรารี Apache PdfBox เพื่ออ่านและเขียน Pdf
ดังนั้นการเปรียบเทียบไฟล์ PDF ขนาดใหญ่จึงอาจใช้หน่วยความจำได้มาก ฉันยังไม่พบวิธีเขียน Pdf ที่แตกต่างกันทีละหน้าด้วย PdfBox แต่มีวิธีแก้ไขบางอย่าง
ขณะนี้มี CompareResults ที่แตกต่างกันสองรายการ ซึ่งมีกลยุทธ์ที่แตกต่างกันในการสลับเพจไปยังดิสก์ และด้วยเหตุนี้จึงจำกัดการใช้หน่วยความจำ
การใช้งาน CompareResult ที่แตกต่างกันสามารถใช้ได้ดังนี้:
new PdfComparator ( "expected.pdf" , "actual.pdf" , new CompareResultWithPageOverflow ()). compare ();
นอกจากนี้ยังมีการตั้งค่าภายในสำหรับขีดจำกัดหน่วยความจำที่สามารถเปลี่ยนแปลงได้ เพียงเพิ่มไฟล์ชื่อ "application.conf" ลงในรูทของ classpath ไฟล์นี้สามารถมีการตั้งค่าบางส่วนหรือทั้งหมดต่อไปนี้เพื่อเขียนทับค่าเริ่มต้นที่ให้ไว้ที่นี่:
imageCacheSizeCount=30
PdfBox แคชรูปภาพจำนวนเท่าใด
maxImageSizeInCache=100000
ขนาดสูงสุดของรูปภาพโดยคร่าวๆ ที่ถูกแคช เพื่อป้องกันไม่ให้รูปภาพขนาดใหญ่มากถูกแคช
ผสาน CacheSizeMB=100
เมื่อ Pdfs ถูกเขียนบางส่วนและผสานในภายหลัง นี่คือแคชหน่วยความจำที่ได้รับการกำหนดค่าสำหรับอินสแตนซ์ PdfBox ที่ทำการรวม
swapCacheSizeMB=100
เมื่อ Pdfs ถูกเขียนเพียงบางส่วน นี่คือแคชหน่วยความจำที่ถูกกำหนดค่าสำหรับอินสแตนซ์ PdfBox ที่ทำการเขียนบางส่วน
documentCacheSizeMB=200
นี่คือขนาดแคชที่กำหนดค่าไว้สำหรับอินสแตนซ์ PdfBox ซึ่งจะโหลดเอกสารที่มีการเปรียบเทียบ
การประมวลผลแบบขนาน = true
เมื่อตั้งค่าเป็นเท็จ จะปิดใช้งานการประมวลผลแบบขนานทั้งหมดและประมวลผลทุกอย่างในเธรดเดียว
โดยรวมหมดเวลาในนาที=15
ตั้งค่าการหมดเวลาโดยรวม นี่เป็นมาตรการด้านความปลอดภัยในการตรวจจับการหยุดชะงักที่อาจเกิดขึ้น การเปรียบเทียบที่ซับซ้อนอาจใช้เวลานานกว่า ดังนั้นค่านี้อาจต้องเพิ่มขึ้น
ผู้ดำเนินการTimeoutInSeconds=60
ตั้งค่าการหมดเวลาเพื่อรอให้ตัวดำเนินการเสร็จสิ้นหลังจากถึงการหมดเวลาโดยรวม ไม่น่าเป็นไปได้ที่คุณจะต้องเปลี่ยนแปลงสิ่งนี้
ดังนั้นในการกำหนดค่าเริ่มต้นนี้ PdfBox ควรใช้ RAM สูงสุด 400MB สำหรับแคชก่อนที่จะเปลี่ยนเป็นดิสก์ ฉันมีประสบการณ์ที่ดีในการให้พื้นที่ฮีป 2GB แก่ JVM
ขอขอบคุณ Chethan Rao มาก [email protected] ที่ช่วยฉันวินิจฉัยปัญหาหน่วยความจำไม่เพียงพอ และให้แนวคิดเกี่ยวกับการเขียนบางส่วนและการรวม PDF ที่สร้างขึ้น