compare pdf java – JavaでPDFファイルをプログラムで比較する方法
If you’re a Java developer who needs to compare pdf java files quickly and accurately, you’ve landed in the right place. Whether you’re building a content‑management system, adding version‑control to legal contracts, or automating QA for generated reports, manual side‑by‑side checks are error‑prone and time‑consuming. GroupDocs.Comparison for Java gives you a single, reliable API that detects insertions, deletions, formatting changes, and even moved paragraphs—all without you having to write complex diff logic yourself.
In this guide we’ll walk through every step required to set up the library, run comparisons on files, streams, or cloud storage, extract change coordinates, and handle large‑document scenarios. You’ll also get practical tips for performance tuning, common pitfalls, and real‑world use‑case examples so you can ship a robust solution faster.
クイック回答
- JavaでPDFファイルを比較できるライブラリは何ですか? GroupDocs.Comparison for Java.
- ライセンスは必要ですか? 学習には無料トライアルで十分です。製品環境ではフルライセンスが必要です。
- 必要なJavaバージョンはどれですか? 最低 Java 8、推奨は Java 11 以上です。
- ドキュメントをディスクに保存せずに比較できますか? はい –
InputStreamベースのオーバーロードを使用して、すべてメモリ上で保持できます。 - 変更座標はどう取得しますか?
compareを呼び出す前にCompareOptionsでsetCalculateCoordinates(true)を呼び出します。
JavaでPDFファイルを比較する方法(compare pdf java)?
Load the two PDFs with a Comparer instance, configure CompareOptions as needed, and call compare. The method returns a ChangeInfo[] array that tells you exactly what changed, where, and how. This whole workflow can be written in under ten lines of Java, and the library takes care of all format‑specific quirks for you.
“compare pdf files java” とは何ですか?
The phrase compare pdf files java refers to the programmatic process of analyzing two PDF (or supported) documents in a Java application to produce a detailed diff. The diff includes inserted, deleted, and modified text, images, tables, and even moved sections, packaged as a structured list that can be rendered, logged, or sent to downstream services.
なぜ GroupDocs.Comparison for Java を使用するのか?
GroupDocs.Comparison supports over 60 input and output formats, including PDF, DOCX, XLSX, PPTX, HTML, and images, while keeping layout intact. It can process multi‑hundred‑page files without loading the whole document into memory, delivering results in under a second for typical 50‑page PDFs. Built‑in options let you ignore style changes, detect moved content, and calculate page coordinates for each change.
JavaでPDFファイルをプログラム的に比較する方法
Below is the end‑to‑end flow you’ll follow in your project. Each step is explained before the corresponding placeholder, so you always know why the code is there.
前提条件と必要なもの
- Java Development Kit (JDK) – バージョン 8 以上(Java 11+ はガベージコレクションとモジュールサポートが向上します)。
- IDE – IntelliJ IDEA、Eclipse、または Maven を認識できるエディタ。
- Maven – 依存関係管理に使用します。チュートリアルは Maven の標準
pom.xmlを使用します。 - サンプルドキュメント – テスト用にわずかな差異がある2つのPDF(または任意のサポート形式)。
GroupDocs.Comparison for Java の設定
Maven 設定
First, add the GroupDocs repository and dependency to your pom.xml. Keep the block exactly as shown:
<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 ダウンロードページで最新の安定版を確認してください。新しいリリースでは追加フォーマットのサポートやパフォーマンス向上が行われることが多いです。
一般的な設定問題と解決策
- “Repository not found” –
<repositories>要素が<dependencies>の 前 にあることを確認してください。 - “ClassNotFoundException” – Maven のリフレッシュ(例: IntelliJ の Maven → Reload project)を実行して JAR をクラスパスに取得してください。
ライセンスオプションの説明
- Free Trial – 学習や小規模デモに最適です。
- Temporary License – 拡張評価のために30日間のキーをリクエストします。
- Full License – 本番環境、無制限のファイルサイズ、優先サポートに必要です。
基本的なプロジェクト構造
your-project/
├── src/main/java/
│ └── com/yourcompany/comparison/
│ └── DocumentComparison.java
├── src/test/resources/
│ ├── source.docx
│ └── target.docx
└── pom.xml
コア実装:ステップバイステップガイド
Comparer クラスの理解
The Comparer class is the central entry point for all comparison operations in GroupDocs.Comparison.
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処理時のメモリリークを防止します。
機能 1: 変更座標の取得
This feature returns the exact page‑level X/Y coordinates for every detected change, enabling you to build visual diff viewers.
使用シーン
- 編集箇所をハイライトするウェブベースのドキュメントレビュアーを構築する場合。
- 各変更の場所を特定する監査ログを生成する場合。
- アノテーションオーバーレイをサポートする 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);
CompareOptions は比較動作を設定し、座標計算の有効化などを行います。
座標計算を有効にする:
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());
}
パフォーマンス注記: 座標を有効にするとおおよそ 15‑20 % のオーバーヘッドが増加します。位置データが不要な大量差分ジョブでは無効にしてください。
機能 2: ファイルパスから変更を取得
If you simply need a list of what changed, this method returns a lightweight ChangeInfo[] without coordinates.
ChangeInfo は検出された単一の変更を表し、タイプと位置を含みます。
適したケース
- プレーンテキストの変更サマリーを生成する場合。
- 数千のドキュメントペアを比較する夜間バッチジョブを実行する場合。
- 2つのバージョンが同一かどうかを迅速に確認する場合。
実装
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.length を確認してください。空配列は2つのドキュメントが同一であることを意味し、下流処理をスキップできます。
機能 3: ストリームでの操作
Streams let you compare files that live in memory, on a network share, or in cloud storage without touching the local filesystem.
一般的なユースケース
- Spring Boot コントローラでファイルアップロードを受け取り、即座に比較する場合。
- AWS S3、Azure Blob、Google Cloud Storage から直接
ByteArrayInputStreamに PDF を取得する場合。 - データベースの BLOB カラムに保存されたドキュメントを比較する場合。
ストリーム実装
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を扱う際に重要です。
機能 4: 対象テキストの抽出
Sometimes you need the exact snippet of text that was added or removed, for email alerts or change‑log entries.
実用的な応用例
- 挿入された段落を含む通知メールを送信する場合。
- “旧テキスト vs. 新テキスト” を並べて表示する 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);
}
}
フィルタリングのヒント: ChangeInfo.getChangeType() を使用して、挿入 (INSERT) または削除 (DELETE) のみを対象にします。
一般的な落とし穴と回避策
1. ファイルパスの問題
問題: ファイルが存在するにもかかわらず “File not found”。
解決策: 開発中は絶対パスを使用するか、IDE の作業ディレクトリを確認してください。Windows ではバックスラッシュ (\\) をエスケープするか、スラッシュ (/) を使用します。
// Good
String path = "C:/Users/yourname/documents/test.docx";
// Or
String path = "C:\\Users\\yourname\\documents\\test.docx";
2. 大容量ファイルでのメモリリーク
問題: 200ページのPDFを比較すると OutOfMemoryError が発生。
解決策: 常に Comparer を try‑with‑resources ブロックでラップし、必要なページだけをメモリに保持するストリームベースのオーバーロードを優先してください。
3. サポートされていないファイル形式
問題: 特定のレガシーフォーマットで例外が発生。
解決策: 公式の supported‑formats リストを確認してください(GroupDocs は 60+ フォーマットをサポート)。リストにない形式は、比較前に PDF または DOCX に変換してください。
4. パフォーマンス問題
問題: 期待より比較に時間がかかる。
解決策:
- 必要でない限り座標計算を無効にする。
- 実際に移動ブロック検出が必要な場合のみ
CompareOptions.setDetectMovedBlocks(true)を使用する。 - スレッドプールで独立した比較ジョブを並列化する。
パフォーマンス最適化のヒント
適切なオプションの選択
CompareOptions options = new CompareOptions.Builder()
.setCalculateCoordinates(false) // Only enable when needed
.setDetectStyleChanges(false) // Skip formatting if you only care about content
.build();
メモリ管理
- すべてを一度に読み込むのではなく、バッチ処理でドキュメントを処理する。
- 50 MB を超えるファイルにはストリーミング API を使用する。
- try‑with‑resources に依存してクリーンアップを保証する。
キャッシュ戦略
// Pseudo-code for caching concept
String cacheKey = generateCacheKey(sourceFile, targetFile);
if (cache.contains(cacheKey)) {
return cache.get(cacheKey);
}
実務シナリオとソリューション
シナリオ 1: コンテンツ管理システム
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();
}
}
}
シナリオ 2: 自動品質保証
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;
}
}
シナリオ 3: バッチドキュメント処理
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);
}
});
}
高度な機能とベストプラクティス
異なるファイル形式の取り扱い
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: 同時に2つ以上のドキュメントを比較できますか?
A: GroupDocs.Comparison は一度に1組のペアのみ比較します。マルチドキュメントのバージョン管理では、ドキュメントリストを反復し、連続するペアごとに比較し、得られた ChangeInfo[] を後で集計できるように保存します。
try (Comparer comparer = new Comparer(sourceDocument)) {
comparer.add(targetDocument1);
comparer.add(targetDocument2);
comparer.add(targetDocument3);
// Now compare against all targets
}
Q: 100 MB 以上の非常に大きなドキュメントはどのように扱うべきですか?
A:
- 正確な位置が不要な場合は座標計算を無効にする。
- ファイル全体を RAM に読み込まないよう、ストリームベースの API を優先する。
- 特定セクションの変更だけが必要な場合はページ範囲に分割して処理する。
- JVM ヒープ使用量を監視し、
-Xmxを適切に調整する。
Q: 出力で変更箇所をビジュアルにハイライトする方法はありますか?
A: はい。ChangeInfo[] を取得した後、GroupDocs.Watermark や任意の PDF ライブラリを使用して新しい PDF を生成し、返された座標に矩形を描画できます。これにより、エンドユーザーが任意の PDF ビューアで確認できる “赤線” バージョンが作成されます。
CompareOptions options = new CompareOptions.Builder()
.setShowInsertedContent(true)
.setShowDeletedContent(true)
.setGenerateOutputDocument(true)
.build();
Q: パスワード保護されたドキュメントはどう扱いますか?
A: Comparer コンストラクタにパスワードを渡すか、compare 呼び出し前に LoadOptions オブジェクトに設定します。ライブラリはメモリ内でドキュメントを復号するため、パスワードがファイルシステムに触れることはありません。
LoadOptions loadOptions = new LoadOptions();
loadOptions.setPassword("your-password");
try (Comparer comparer = new Comparer(protectedDocument, loadOptions)) {
// Comparison logic here
}
Q: 変更検出のカスタマイズは可能ですか?
A: もちろんです。CompareOptions には setIgnoreFormatting(true)、setDetectMovedBlocks(true)、setGranularity(Granularity.WORD) などのフラグがあります。これらをビジネスルールに合わせて調整してください。例として、フォント変更は無視しつつ段落の移動は検出できます。
CompareOptions options = new CompareOptions.Builder()
.setDetectStyleChanges(false) // Ignore formatting changes
.setSensitivityOfComparison(100) // Adjust sensitivity (0‑100)
.build();
Q: Spring Boot との統合で最適な方法は何ですか?
A: ライセンスパスを注入する @Service Bean を作成し、MultipartFile アップロードを受け付ける @RestController エンドポイントを公開します。コントローラ内で MultipartFile を InputStream に変換し、ストリームベースの比較メソッドを呼び出します。ChangeInfo[] を JSON として返し、フロントエンドでレンダリングできるようにします。
@Service
public class DocumentComparisonService {
public ComparisonResult compare(MultipartFile source, MultipartFile target) {
// Implementation using the techniques from this guide
}
}
追加リソース
最終更新日: 2026-06-15
テスト環境: GroupDocs.Comparison 25.2 for Java
作者: GroupDocs
for (ChangeInfo change : changes) {
if (change.getType() == ComparisonAction.INSERT) {
System.out.println("Added: " + change.getText());
}
}