一個簡單的 Java 程式庫,用於比較兩個 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)時,有一個簡單的互動式 UI。它允許您選擇要比較的文件,也可以標記要忽略的區域並將其寫入忽略文件。
在 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 將預期 .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 也回傳 equals 狀態:
boolean isEquals = new PdfComparator ( "expected.pdf" , "actual.pdf" ). compare (). writeTo ( "diffOutput" );
if (! isEquals ) {
System . out . println ( "Differences found!" );
}
可以使用字串、檔案、路徑或輸入流等檔案名稱來呼叫比較方法。
也可以定義在比較過程中忽略的矩形區域。為此,需要建立一個文件,其中定義要忽略的區域。檔案格式為 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(String password) 或 withActualPassword(String password) 方法將密碼提供給比較器。
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 命令列參數指定替換設定檔。
或者,您可以透過系統環境變數或使用 -DvariableName= 作為 Jvm 參數來指定參數
以程式設計方式指定不同配置位置的另一種方法是建立一個新的 ConfigFileEnvironment(...) 並將其傳遞給 PdfCompare.withEnvironment(...)。
所有可以透過 application.conf 檔案更改的設定也可以透過 API 以程式設計方式更改。為此,您可以使用以下程式碼:
new PdfComparator ( "expected.pdf" , "actual.pdf" )
. withEnvironment ( new SimpleEnvironment ()
. setActualColor ( Color . green )
. setExpectedColor ( Color . blue ))
. compare ();
SimpleEnvironment 將所有未指派的設定委託給預設環境。
透過環境您可以配置記憶體設定(見上文)和以下設定:
分辨率=300
設定呈現 Pdf 頁面的 DPI。預設值為 300。
預期顏色=00B400(綠色)
預期顏色是用於預期但不存在的像素的顏色。顏色以 HTML-Stlye 格式指定(不含前導「#」):前兩個字元以十六進位定義顏色的紅色部分。接下來的兩個字元定義顏色的綠色部分。最後兩個字元定義要使用的顏色的藍色部分。
實際顏色=D20000(紅色)
實際顏色是用於存在但不是預期的像素的顏色。顏色以 HTML-Stlye 格式指定(不含前導「#」):前兩個字元以十六進位定義顏色的紅色部分。接下來的兩個字元定義顏色的綠色部分。最後兩個字元定義要使用的顏色的藍色部分。
tempDir=System.property("java.io.tmpdir")
設定寫入暫存檔案的目錄。預設為 java.io.tmpdir 的 java 預設值,它通常會決定係統特定的預設值,例如大多數 UNIX 系統上的 /tmp。
allowedDifferenceInPercentPerPage=0.2
每頁可能不同的像素百分比。預設值為 0。這樣,只有當超過給定百分比的像素差異時,才會報告差異。百分比按每頁計算。當您 addEqualPagesToResult 時,差異仍然會標記在輸出檔案中。
並行處理=true
當設定為 false 時,停用所有並行處理並在單一執行緒中處理所有內容。
addEqualPagesToResult=true
當設定為 false 時,僅將有差異的頁面新增至結果中,這就是產生的差異 PDF 文件。
failOnMissingIgnoreFile=false
當設定為 true 時,遺失的忽略檔案會導致異常。否則它會被忽略,並且只寫入訊息等級的日誌訊息。
CompareResults 有幾種不同的實現,具有不同的特徵。可用於控制系統行為的某些方面,特別是記憶體消耗。
使用 PdfCompare 時,了解一些內部原理是有好處的。簡而言之,PdfCompare 在比較兩個 PDF 時會做什麼。
PdfCompare 使用 Apache PdfBox 函式庫來讀取和寫入 Pdf。
因此比較大的 Pdf 會佔用大量記憶體。我還沒有找到一種方法來使用 PdfBox 逐頁增量地編寫差異 Pdf,但有一些解決方法。
目前有兩種不同的 CompareResults,它們具有不同的將頁面交換到磁碟的策略,從而限制記憶體消耗。
可以使用不同的 CompareResult 實現,如下所示:
new PdfComparator ( "expected.pdf" , "actual.pdf" , new CompareResultWithPageOverflow ()). compare ();
還有一些記憶體限制的內部設定可以更改。只需將名為「application.conf」的檔案新增至類別路徑的根目錄即可。該文件可以具有以下部分或全部設定來覆蓋此處給出的預設值:
影像快取大小計數=30
PdfBox 快取了多少張圖片
maxImageSizeInCache=100000
快取圖像的粗略最大大小,以防止快取非常大的圖像
合併快取大小MB=100
當 Pdf 部分寫入並稍後合併時,這是為執行合併的 PdfBox 實例配置的記憶體快取。
交換快取大小MB=100
當 Pdf 被部分寫入時,這是為執行部分寫入的 PdfBox 實例配置的記憶體快取。
文件快取大小MB=200
這是為 PdfBox 實例配置的快取大小,用於載入比較的文件。
並行處理=true
當設定為 false 時,停用所有並行處理並在單一執行緒中處理所有內容。
整體超時時間=15
設定總超時時間。這是檢測可能的死鎖的安全措施。複雜的比較可能需要更長的時間,因此可能需要增加該值。
執行者超時時間=60
設定達到總體逾時後等待執行程序完成的逾時。您不太可能需要更改此設定。
因此,在此預設配置中,PdfBox 在交換到磁碟之前應使用最多 400MB 的 RAM 作為快取。我在向 JVM 授予 2GB 堆空間方面擁有豐富的經驗。
非常感謝 Chethan Rao [email protected] 幫助我診斷記憶體不足問題並提供部分寫入和合併生成的 PDF 的想法。