| categories |
|
|||||
|---|---|---|---|---|---|---|
| date | 2025-12-20 | |||||
| description | 學習如何使用 GroupDocs.Comparison 在 Java 中比較 PDF 檔案。此一步一步的教學涵蓋文件比較的最佳實踐、程式碼範例、效能技巧與疑難排解。 | |||||
| keywords | java compare documents programmatically, java document diff library, compare two files java, java text comparison, groupdocs comparison java, document version control java, compare pdf files java, document comparison best practices | |||||
| lastmod | 2025-12-20 | |||||
| linktitle | Java Document Comparison Guide | |||||
| tags |
|
|||||
| title | 如何在 Java 中以程式方式比較 PDF 檔案 | |||||
| type | docs | |||||
| url | /zh-hant/java/basic-comparison/java-document-comparison-groupdocs-comparison/ | |||||
| weight | 1 |
有沒有曾經手動比較兩個文件版本,眯著眼在螢幕上找出差異?如果你是 Java 開發者,可能已經多次遇到這個挑戰。無論是建立內容管理系統、實作版本控制,或只是需要追蹤法律文件的變更,compare pdf files java 都能為你節省大量繁瑣的時間。
好消息是?使用 GroupDocs.Comparison for Java,你可以自動化整個流程。這份完整指南將帶你了解在 Java 應用程式中實作文件比較所需的一切。你將學會如何偵測變更、提取座標,甚至處理不同的檔案格式——全部以乾淨且高效的程式碼完成。
完成本教學後,你將對文件比較技術有扎實的了解,並能在自己的專案中實作。讓我們開始吧!
- 什麼函式庫可以在 Java 中比較 PDF 檔案? GroupDocs.Comparison for Java.
- 我需要授權嗎? 免費試用可用於學習;正式環境需購買完整授權。
- 需要哪個 Java 版本? 最低支援 Java 8,建議使用 Java 11 以上。
- 可以在不寫入磁碟的情況下比較文件嗎? 可以,使用串流在記憶體中比較。
- 如何取得變更座標? 在
CompareOptions中啟用setCalculateCoordinates(true)。
在 Java 中比較 PDF 檔案指的是以程式方式分析兩個 PDF(或其他)文件,找出新增、刪除與修改的部分。此過程會回傳結構化的變更清單,可用於報表、視覺標示或自動化工作流程。
- 速度與準確度: 支援超過 60 種格式,保持高度忠實度。
- 內建文件比較最佳實踐,例如忽略樣式變更或偵測內容移動。
- 可擴充性: 可處理大型檔案、串流與雲端儲存。
- 可擴充性: 可自訂比較選項以符合任何業務規則。
- Java Development Kit (JDK) – 版本 8 或以上(建議使用 Java 11 以上以獲得更佳效能)
- IDE – IntelliJ IDEA、Eclipse 或你喜愛的 Java IDE
- Maven – 用於相依管理(大多數 IDE 內建)
- 基本的 Java 程式設計(類別、方法、try‑with‑resources)
- 熟悉 Maven 相依(我們會一步步說明設定)
- 了解檔案 I/O 操作(有助但非必須)
準備好幾個範例文件——Word、PDF 或文字檔都很適合。若沒有,可自行建立兩個內容略有差異的簡易文字檔來測試。
首先,將 GroupDocs 的儲存庫與相依加入你的 pom.xml。請保持區塊內容與示範完全相同:
<repositories>
<repository>
<id>repository.groupdocs.com</id>
<name>GroupDocs Repository</name>
<url>https://releases.groupdocs.com/comparison/java/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-comparison</artifactId>
<version>25.2</version>
</dependency>
</dependencies>小技巧:請隨時在 GroupDocs 官方網站確認最新版本。本文撰寫時的版本為 25.2,但更新的版本可能包含額外功能或錯誤修正。
- 「找不到儲存庫」 – 確認
<repositories>區塊位於<dependencies>之前。 - 「ClassNotFoundException」 – 重新整理 Maven 相依(IntelliJ:Maven → Reload project)。
- 免費試用 – 適合學習與小型專案。
- 暫時授權 – 申請 30 天金鑰以延長評估。
- 完整授權 – 正式環境必須使用。
your-project/
├── src/main/java/
│ └── com/yourcompany/comparison/
│ └── DocumentComparison.java
├── src/test/resources/
│ ├── source.docx
│ └── target.docx
└── pom.xml
Comparer 類別是文件比較的主要介面:
import com.groupdocs.comparison.Comparer;
try (Comparer comparer = new Comparer("sourceFilePath")) {
comparer.add("targetFilePath");
// Your comparison logic goes here
}為什麼使用 try‑with‑resources? Comparer 實作了 AutoCloseable,因此此寫法能確保記憶體與檔案句柄正確釋放——在處理大型 PDF 時非常重要。
此功能可精確告訴每筆變更發生的位置——就像文件編輯的 GPS 座標。
- 建構視覺差異檢視器
- 實作精確的稽核報告
- 在 PDF 檢視器中標示變更以供法律審查
import com.groupdocs.comparison.Comparer;
import com.groupdocs.comparison.result.ChangeInfo;
String sourceFilePath = "path/to/source.docx";
String targetFilePath = "path/to/target.docx";
try (Comparer comparer = new Comparer(sourceFilePath)) {
// Add the target document for comparison.
comparer.add(targetFilePath);啟用座標計算:
import com.groupdocs.comparison.options.CompareOptions;
final Path resultPath = comparer.compare(
new CompareOptions.Builder()
.setCalculateCoordinates(true)
.build());提取並處理變更資訊:
ChangeInfo[] changes = comparer.getChanges();
for (ChangeInfo change : changes) {
System.out.printf("Change Type: %s, X: %f, Y: %f, Text: %s%n",
change.getType(), change.getBox().getX(), change.getBox().getY(), change.getText());
}效能說明:計算座標會增加額外負擔,僅在需要時才啟用。
若只需要簡單的變更清單,這是首選方法。
- 快速變更摘要
- 簡易差異報告
- 批次處理多組文件對比
try (Comparer comparer = new Comparer(sourceFilePath)) {
comparer.add(targetFilePath);執行比較而不使用額外選項:
final Path resultPath = comparer.compare();
ChangeInfo[] changes = comparer.getChanges();
System.out.println("\nCount of changes: " + changes.length);
}最佳實踐:務必檢查 changes 陣列的長度——若為空陣列表示文件完全相同。
適用於 Web 應用、微服務,或任何檔案位於記憶體或雲端的情境。
- 在 Spring Boot 控制器中處理檔案上傳
- 從 AWS S3 或 Azure Blob Storage 取得文件
- 處理儲存在資料庫 BLOB 欄位的 PDF
import java.io.FileInputStream;
import java.io.InputStream;
try (InputStream sourceStream = new FileInputStream(sourceFilePath);
InputStream targetStream = new FileInputStream(targetFilePath);
Comparer comparer = new Comparer(sourceStream)) {
comparer.add(targetStream);以相同的比較呼叫繼續:
final Path resultPath = comparer.compare();
ChangeInfo[] changes = comparer.getChanges();
System.out.println("\nCount of changes: " + Arrays.toString(changes).length);
}記憶體提示:try‑with‑resources 區塊會自動關閉串流,避免大型 PDF 產生記憶體洩漏。
有時需要取得變更的精確文字——非常適合變更日誌或通知。
- 建構變更日誌 UI
- 以插入/刪除的文字發送電子郵件警示
- 進行內容合規稽核
try (Comparer comparer = new Comparer(sourceFilePath)) {
comparer.add(targetFilePath);
final Path resultPath = comparer.compare();
ChangeInfo[] changes = comparer.getChanges();
for (ChangeInfo change : changes) {
String text = change.getText();
System.out.println(text);
}
}篩選提示:聚焦特定變更類型:
for (ChangeInfo change : changes) {
if (change.getType() == ComparisonAction.INSERT) {
System.out.println("Added: " + change.getText());
}
}問題:即使檔案存在仍出現「File not found」。
解決方案:開發時使用絕對路徑或確認工作目錄。Windows 上請對反斜線做跳脫或改用正斜線。
// Good
String path = "C:/Users/yourname/documents/test.docx";
// Or
String path = "C:\\Users\\yourname\\documents\\test.docx";問題:大型 PDF 產生 OutOfMemoryError。
解決方案:始終使用 try‑with‑resources,並考慮使用串流 API 或分塊處理文件。
問題:某些格式拋出例外。
解決方案:先檢查支援的格式清單。GroupDocs 支援超過 60 種格式,實作前請先確認。
問題:比較耗時過長。
解決方案:
- 除非必要,請停用座標計算。
- 使用適當的
CompareOptions。 - 盡可能將批次作業平行化。
CompareOptions options = new CompareOptions.Builder()
.setCalculateCoordinates(false) // Only enable when needed
.setDetectStyleChanges(false) // Skip formatting if you only care about content
.build();- 以批次方式處理文件,避免一次載入全部。
- 大檔案使用串流 API。
- 在
finally區塊中正確清理,或依賴 try‑with‑resources。
對於頻繁比較的文件,快取比較結果:
// Pseudo-code for caching concept
String cacheKey = generateCacheKey(sourceFile, targetFile);
if (cache.contains(cacheKey)) {
return cache.get(cacheKey);
}public class ArticleVersionComparison {
public List<ChangeInfo> compareVersions(String oldVersion, String newVersion) {
try (Comparer comparer = new Comparer(oldVersion)) {
comparer.add(newVersion);
final Path result = comparer.compare();
return Arrays.asList(comparer.getChanges());
} catch (Exception e) {
log.error("Failed to compare article versions", e);
return Collections.emptyList();
}
}
}public boolean validateReportAgainstTemplate(InputStream report, InputStream template) {
try (Comparer comparer = new Comparer(template)) {
comparer.add(report);
comparer.compare();
ChangeInfo[] changes = comparer.getChanges();
// Only allow certain types of changes
return Arrays.stream(changes)
.allMatch(change -> isAllowedChange(change));
} catch (Exception e) {
return false;
}
}public void processBatchComparison(List<DocumentPair> documents) {
documents.parallelStream().forEach(pair -> {
try (Comparer comparer = new Comparer(pair.getSource())) {
comparer.add(pair.getTarget());
Path result = comparer.compare();
// Process results...
} catch (Exception e) {
log.error("Failed to process document pair: " + pair, e);
}
});
}- 檢查文件編碼(UTF‑8 與其他編碼)。
- 留意隱藏字元或格式差異。
- 使用效能分析找出瓶頸。
- 調整
CompareOptions,跳過不必要的功能。
- 檢查 classpath 與相依版本。
- 確認授權檔正確放置於伺服器上。
- 檢查檔案權限與網路存取。
public boolean isFormatSupported(String filePath) {
String extension = getFileExtension(filePath);
List<String> supportedFormats = Arrays.asList(
".docx", ".pdf", ".txt", ".rtf", ".odt", // Add more as needed
);
return supportedFormats.contains(extension.toLowerCase());
}CompareOptions largeDocOptions = new CompareOptions.Builder()
.setCalculateCoordinates(false) // Saves memory
.setDetectStyleChanges(false) // Focuses on content only
.setWordsLimit(1000) // Limits processing scope
.build();public ComparisonResult compareDocuments(String source, String target) {
try (Comparer comparer = new Comparer(source)) {
comparer.add(target);
Path result = comparer.compare();
return ComparisonResult.success(comparer.getChanges());
} catch (SecurityException e) {
log.error("Access denied when comparing documents", e);
return ComparisonResult.failure("Access denied");
} catch (IOException e) {
log.error("IO error during document comparison", e);
return ComparisonResult.failure("File access error");
} catch (Exception e) {
log.error("Unexpected error during comparison", e);
return ComparisonResult.failure("Comparison failed");
}
}Q: GroupDocs.Comparison 最低需要哪個 Java 版本?
A: 最低支援 Java 8,但建議使用 Java 11 以上以獲得更佳效能與安全性。
Q: 可以同時比較超過兩個文件嗎?
A:
try (Comparer comparer = new Comparer(sourceDocument)) {
comparer.add(targetDocument1);
comparer.add(targetDocument2);
comparer.add(targetDocument3);
// Now compare against all targets
}Q: 如何處理非常大的文件(100 MB 以上)?
A:
- 除非必要,停用座標計算。
- 使用串流 API。
- 以區塊或頁面方式處理文件。
- 密切監控記憶體使用情況。
Q: 是否有方式在輸出中視覺化標示變更?
A:
CompareOptions options = new CompareOptions.Builder()
.setShowInsertedContent(true)
.setShowDeletedContent(true)
.setGenerateOutputDocument(true)
.build();Q: 如何處理受密碼保護的文件?
A:
LoadOptions loadOptions = new LoadOptions();
loadOptions.setPassword("your-password");
try (Comparer comparer = new Comparer(protectedDocument, loadOptions)) {
// Comparison logic here
}Q: 能自訂變更偵測的方式嗎?
A:
CompareOptions options = new CompareOptions.Builder()
.setDetectStyleChanges(false) // Ignore formatting changes
.setSensitivityOfComparison(100) // Adjust sensitivity (0‑100)
.build();Q: 與 Spring Boot 整合的最佳方式是什麼?
A:
@Service
public class DocumentComparisonService {
public ComparisonResult compare(MultipartFile source, MultipartFile target) {
// Implementation using the techniques from this guide
}
}最後更新: 2025-12-20
測試環境: GroupDocs.Comparison 25.2 for Java
作者: GroupDocs