Pustaka Java sederhana untuk membandingkan dua file PDF. File dirender dan dibandingkan piksel demi piksel. Tidak ada perbandingan teks.
Masukkan saja sebagai ketergantungan. Silakan periksa versi terbaru yang tersedia:
< dependencies >
< dependency >
< groupId >de.redsix groupId >
< artifactId >pdfcompare artifactId >
< version >... version >
dependency >
dependencies >
Ada UI interaktif sederhana, saat Anda memulai file jar tanpa argumen tambahan (yang memulai kelas de.redsix.pdfcompare.Main). Ini memungkinkan Anda memilih file untuk dibandingkan dan juga menandai area yang akan diabaikan dan menulisnya ke file yang diabaikan.
Di samping UI, Anda dapat memberikan file yang diharapkan dan aktual serta parameter tambahan melalui CLI. Untuk mendapatkan bantuan untuk CLI gunakan opsi -h atau --help-.
usage: java -jar pdfcompare-x.x.x-full.jar [EXPECTED] [ACTUAL]
-h,--help Displays this text and exit
...
Namun fokus PdfCompare adalah pada penggunaan yang disematkan sebagai perpustakaan.
new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
Ini akan menghasilkan PDF keluaran yang mungkin menyertakan tanda untuk perbedaan yang ditemukan. PdfCompare merender halaman dari .pdf yang diharapkan dan halaman yang sama dari .pdf sebenarnya menjadi gambar bitmap dan membandingkan kedua gambar ini piksel demi piksel. Piksel yang setara sedikit memudar. Piksel yang berbeda ditandai dengan warna merah dan hijau. Hijau untuk piksel yang ada di .pdf yang diharapkan, tetapi tidak ada di .pdf sebenarnya. Merah untuk piksel yang ada di .pdf sebenarnya, namun tidak ada di .pdf yang diharapkan. Dan terdapat tanda di tepi kertas berwarna magenta untuk menemukan area yang berbeda dengan cepat. Area yang Diabaikan ditandai dengan latar belakang kuning. Halaman yang diharapkan tetapi tidak datang ditandai dengan batas merah. Halaman yang muncul, namun tidak diharapkan, ditandai dengan batas hijau.
Metode perbandingan mengembalikan CompareResult, yang dapat ditanyakan:
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
Untuk kenyamanan, writeTo juga mengembalikan status sama dengan:
boolean isEquals = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
if (! isEquals ) {
System . out . println ( "Differences found!" );
}
Metode perbandingan dapat dipanggil dengan nama file seperti Strings, Files, Paths atau InputStreams.
Dimungkinkan juga untuk menentukan area persegi panjang yang diabaikan selama perbandingan. Untuk itu, sebuah file perlu dibuat, yang mendefinisikan area yang akan diabaikan. Format filenya adalah JSON (atau sebenarnya superset yang disebut HOCON) dan memiliki bentuk sebagai berikut:
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.
}
]
Jika file pengecualian yang diberikan tidak ditemukan, file tersebut diabaikan dan perbandingan dilakukan tanpa pengecualian.
Pengecualian diberikan dalam kode sebagai berikut:
new PdfComparator ( "expected.pdf" , "actual.pdf" ). withIgnore ( "ignore.conf" ). compare ();
Alternatifnya, Pengecualian dapat ditambahkan melalui API sebagai berikut:
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withIgnore ( new PageArea ( 1 , 230 , 350 , 450 , 420 ))
. withIgnore ( new PageArea ( 2 ))
. compare ();
Saat Anda ingin membandingkan file PDF yang dilindungi kata sandi, Anda dapat memberikan kata sandi ke Pembanding melalui metode withExpectedPassword(String password) atau withActualPassword(String password) masing-masing.
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withExpectedPassword ( "somePwd" )
. withActualPassword ( "anotherPwd" )
. compare ();
PdfCompare dapat dikonfigurasi dengan file konfigurasi. File konfigurasi default disebut "application.conf" dan harus ditempatkan di root classpath.
PdfCompare menggunakan Lightbend Config (sebelumnya disebut TypeSafe Config) untuk membaca file konfigurasinya. Jika Anda ingin menentukan file konfigurasi lain, Anda dapat mengetahui lebih lanjut di sini: https://github.com/lightbend/config#standard-behavior. Secara khusus, Anda dapat menentukan file konfigurasi pengganti dengan argumen baris perintah -Dconfig.file=path/to/file.
Alternatifnya, Anda dapat menentukan parameter melalui variabel lingkungan sistem atau sebagai parameter Jvm dengan -DvariableName=
Cara lain untuk menentukan lokasi konfigurasi yang berbeda secara terprogram adalah dengan membuat ConfigFileEnvironment(...) baru dan meneruskannya ke PdfCompare.withEnvironment(...).
Semua pengaturan yang dapat diubah melalui file application.conf juga dapat diubah secara terprogram melalui API. Untuk melakukannya Anda dapat menggunakan kode berikut:
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withEnvironment ( new SimpleEnvironment ()
. setActualColor ( Color . green )
. setExpectedColor ( Color . blue ))
. compare ();
SimpleEnvironment mendelegasikan semua pengaturan, yang tidak ditetapkan, ke Lingkungan default.
Melalui lingkungan Anda dapat mengonfigurasi pengaturan memori (lihat di atas) dan pengaturan berikut:
DPI=300
Menyetel DPI yang digunakan untuk merender halaman Pdf. Standarnya adalah 300.
diharapkanWarna=00B400 (HIJAU)
Warna yang diharapkan adalah warna yang digunakan untuk piksel yang diharapkan, namun ternyata tidak ada. Warna ditentukan dalam format HTML-Stlye (tanpa awalan '#'): Dua karakter pertama menentukan bagian merah warna dalam heksadesimal. Dua karakter berikutnya menentukan bagian hijau dari warna tersebut. Dua karakter terakhir menentukan bagian biru dari warna yang akan digunakan.
warna sebenarnya=D20000 (MERAH)
Warna sebenarnya adalah warna yang digunakan untuk pixel-pixel yang ada, namun tidak diharapkan. Warna ditentukan dalam format HTML-Stlye (tanpa awalan '#'): Dua karakter pertama menentukan bagian merah warna dalam heksadesimal. Dua karakter berikutnya menentukan bagian hijau dari warna tersebut. Dua karakter terakhir menentukan bagian biru dari warna yang akan digunakan.
tempDir=Sistem.properti("java.io.tmpdir")
Menetapkan direktori tempat menulis file sementara. Defaultnya adalah default java untuk java.io.tmpdir, yang biasanya menentukan default spesifik sistem, seperti /tmp pada sebagian besar sistem unix.
diperbolehkanDifferenceInPercentPerPage=0,2
Persentase piksel yang mungkin berbeda per halaman. Standarnya adalah 0. Jika karena alasan tertentu rendering Anda sedikit melenceng atau Anda membiarkan margin kesalahan tertentu, Anda dapat mengonfigurasi persentase piksel yang diabaikan selama perbandingan. Dengan demikian, perbedaan hanya dilaporkan jika perbedaan pikselnya lebih dari persentase tertentu. Persentasenya dihitung per halaman. Bukan berarti perbedaannya masih terlihat di file keluaran, saat Anda menambahkanEqualPagesToResult.
pemrosesan paralel=benar
Jika disetel ke false, nonaktifkan semua pemrosesan paralel dan proses semuanya dalam satu thread.
addEqualPagesToResult=benar
Jika disetel ke false, hanya halaman dengan perbedaan yang ditambahkan ke hasil dan inilah perbedaan yang dihasilkan dokumen PDF.
failOnMissingIgnoreFile=salah
Jika disetel ke true, file abaikan yang hilang akan menyebabkan pengecualian. Jika tidak maka akan diabaikan dan hanya pesan log tingkat info yang ditulis.
Ada beberapa Implementasi CompareResults yang berbeda dengan karakteristik berbeda. Dapat digunakan untuk mengontrol aspek tertentu dari perilaku sistem, khususnya konsumsi memori.
Ada baiknya mengetahui beberapa bagian internal, saat menggunakan PdfCompare. Berikut ini secara singkat apa yang dilakukan PdfCompare ketika membandingkan dua PDF.
PdfCompare menggunakan Perpustakaan Apache PdfBox untuk membaca dan menulis Pdf.
Jadi membandingkan Pdf berukuran besar dapat menghabiskan banyak memori. Saya belum menemukan cara untuk menulis perbedaan Pdf halaman demi halaman secara bertahap dengan PdfBox, tetapi ada beberapa solusi.
Saat ini terdapat dua CompareResults yang berbeda, yang memiliki strategi berbeda untuk menukar halaman ke disk dan dengan demikian membatasi konsumsi memori.
Implementasi CompareResult yang berbeda dapat digunakan sebagai berikut:
new PdfComparator ( "expected.pdf" , "actual.pdf" , new CompareResultWithPageOverflow ()). compare ();
Juga ada beberapa pengaturan internal untuk batas memori, yang dapat diubah. Cukup tambahkan file bernama "application.conf" ke root classpath. File ini dapat memiliki beberapa atau semua pengaturan berikut untuk menimpa pengaturan default yang diberikan di sini:
gambarCacheSizeCount=30
Berapa banyak gambar yang di-cache oleh PdfBox
maxImageSizeInCache=100000
Perkiraan ukuran maksimum gambar yang di-cache, untuk mencegah gambar yang sangat besar di-cache
gabungCacheSizeMB=100
Ketika Pdf ditulis sebagian dan kemudian digabungkan, ini adalah cache memori yang dikonfigurasi untuk instance PdfBox yang melakukan penggabungan.
swapCacheSizeMB=100
Ketika Pdf ditulis sebagian, ini adalah cache memori yang dikonfigurasi untuk instance PdfBox yang melakukan penulisan sebagian.
dokumenCacheSizeMB=200
Ini adalah ukuran cache yang dikonfigurasi untuk contoh PdfBox, yang memuat dokumen yang dibandingkan.
pemrosesan paralel=benar
Jika disetel ke false, nonaktifkan semua pemrosesan paralel dan proses semuanya dalam satu thread.
keseluruhanTimeoutInMinutes=15
Tetapkan batas waktu keseluruhan. Ini adalah langkah pengamanan untuk mendeteksi kemungkinan kebuntuan. Perbandingan yang rumit mungkin memerlukan waktu lebih lama, sehingga nilai ini mungkin harus ditingkatkan.
executorTimeoutInSeconds=60
Menyetel batas waktu untuk menunggu pelaksana selesai setelah waktu tunggu keseluruhan tercapai. Kecil kemungkinan Anda perlu mengubahnya.
Jadi dalam konfigurasi default ini, PdfBox harus menggunakan Ram hingga 400MB untuk cache-nya, sebelum bertukar ke disk. Saya memiliki pengalaman bagus dalam memberikan ruang heap 2GB ke JVM.
Terima kasih banyak kepada Chethan Rao [email protected] karena telah membantu saya mendiagnosis masalah kehabisan memori dan memberikan gagasan tentang penulisan sebagian dan penggabungan PDF yang dihasilkan.