Bandingkan folder java – panduan menggunakan GroupDocs.Comparison
Pernah menghabiskan berjam‑jam memeriksa secara manual file mana yang berubah antara dua versi proyek? Anda tidak sendirian. GroupDocs.Comparison untuk Java membuat tugas membosankan ini menjadi mudah dengan memungkinkan Anda membandingkan dua folder dengan satu panggilan API. Dalam tutorial ini Anda akan belajar cara membandingkan folder java secara efektif, mulai dari penyiapan awal hingga penyetelan kinerja lanjutan untuk basis kode yang besar.
GroupDocs.Comparison untuk Java adalah pustaka yang memungkinkan perbandingan programatik dokumen dan direktori. Ia mendukung lebih dari 70 format input dan output serta dapat memproses direktori dengan hingga 10.000 file tanpa memuat seluruh set file ke memori, menjadikannya pilihan kuat untuk audit skala perusahaan.
Jawaban cepat
- Apa pustaka utama?
groupdocs comparison java - Versi Java yang didukung? Java 8 atau lebih tinggi
- Waktu penyiapan tipikal? 10–15 menit untuk perbandingan dasar
- Apakah lisensi diperlukan? Ya – diperlukan lisensi percobaan atau komersial
- Format output? HTML (default) atau PDF
Apa itu bandingkan folder java?
Frasa “bandingkan folder java” mengacu pada penggunaan API berbasis Java untuk mendeteksi perbedaan—file yang ditambahkan, dihapus, atau dimodifikasi—antara dua pohon direktori. GroupDocs.Comparison menyediakan cara tingkat‑tinggi yang tidak tergantung pada sistem file untuk melakukan operasi ini, mengembalikan laporan HTML atau PDF terperinci yang menyoroti setiap perubahan.
Mengapa membandingkan folder java penting (lebih dari yang Anda kira)
Perbandingan direktori bukan hanya tentang menemukan file yang hilang; ia merupakan titik kontrol kritis untuk integritas data, kepatuhan regulasi, dan stabilitas rilis. Dengan mengotomatisasi proses Anda menghilangkan kesalahan manusia, mempercepat audit, dan memperoleh satu sumber kebenaran yang dapat diarsipkan untuk referensi di masa mendatang.
Manfaat yang terukur
- Kecepatan: Memproses direktori 5.000 file dalam kurang dari 30 detik pada server 8‑core tipikal.
- Cakupan: Mendeteksi perubahan pada lebih dari 70 tipe dokumen, dari DOCX hingga PNG.
- Skalabilitas: Menangani file hingga 2 GB masing‑masing tanpa menghabiskan heap JVM ketika dikonfigurasi dengan mode streaming.
- Akurasi: Melaporkan perbedaan dengan fidelitas 99,9 %, mempertahankan tata letak, tabel, dan gambar.
Prasyarat dan kebutuhan penyiapan
Sebelum kita mulai menulis kode, pastikan lingkungan Anda siap. Berikut yang Anda perlukan (dan mengapa):
Persyaratan esensial
- Java 8 atau lebih tinggi – GroupDocs.Comparison menggunakan fitur bahasa modern dan API terkini.
- Maven 3.6+ – Untuk resolusi dependensi yang handal; penanganan JAR manual rawan kesalahan.
- IDE dengan dukungan Java yang baik – IntelliJ IDEA atau Eclipse direkomendasikan untuk debugging dan refactoring.
- Setidaknya 2 GB RAM – Perbandingan direktori besar dapat mengonsumsi memori signifikan, terutama saat menghasilkan laporan HTML.
Prasyarat pengetahuan
- Sintaks Java dasar (loop, penanganan pengecualian, try‑with‑resources).
- Familiaritas dengan I/O file (
java.nio.file.Path, APIFiles). - Memahami bagian
<dependency>dan<repository>pada Maven.
Opsional namun membantu
- Pengalaman dengan SLF4J/Logback untuk logging.
- Pengetahuan tentang konsep multi‑threading jika Anda berencana memparalelkan perbandingan.
- Pengetahuan dasar HTML untuk menyesuaikan laporan yang dihasilkan.
Menyiapkan GroupDocs.Comparison untuk Java
Mari integrasikan pustaka ini ke dalam proyek Anda. Penyiapan cukup sederhana, namun ada beberapa hal yang perlu diwaspadai.
Konfigurasi Maven
Tambahkan dependensi dan repositori berikut ke pom.xml Anda. Pastikan mengganti placeholder versi dengan nomor rilis terbaru dari situs resmi GroupDocs.
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-comparison</artifactId>
<version>25.2</version>
</dependency>
<repository>
<id>groupdocs-repo</id>
<url>https://repo.groupdocs.com/maven2</url>
</repository>
Tip pro: Selalu verifikasi nomor versi pada halaman unduhan produk; rilis terbaru menyertakan perbaikan kinerja dan dukungan format tambahan.
Penyiapan lisensi (jangan lewatkan ini)
GroupDocs tidak gratis, tetapi mereka menawarkan beberapa opsi lisensi:
- Percobaan gratis: Percobaan 30 hari dengan semua fitur—ideal untuk evaluasi.
- Lisensi sementara: Percobaan diperpanjang untuk lingkungan pengembangan dan pengujian.
- Lisensi komersial: Diperlukan untuk penyebaran produksi.
Dapatkan lisensi Anda dari:
- Beli lisensi untuk produksi
- Dapatkan lisensi sementara untuk pengujian lanjutan
Inisialisasi dasar dan pengujian
Setelah build Maven berhasil, buat kelas uji sederhana yang memuat lisensi dan menjalankan perbandingan minimal. Jika program berjalan tanpa melempar pengecualian, lingkungan Anda telah terkonfigurasi dengan benar.
import com.groupdocs.comparison.Comparison;
import com.groupdocs.comparison.License;
public class InitTest {
public static void main(String[] args) throws Exception {
License license = new License();
license.setLicense("GroupDocs.Comparison.lic");
// Simple sanity check
Comparison comparison = new Comparison();
System.out.println("GroupDocs.Comparison initialized successfully.");
}
}
Jika ini berjalan tanpa error, Anda siap melanjutkan. Jika tidak, periksa kembali pengaturan Maven Anda dan pastikan mesin dapat mengakses server lisensi GroupDocs.
Implementasi inti: perbandingan direktori
Sekarang saatnya membandingkan direktori secara nyata — kami akan mulai dengan implementasi dasar lalu menambahkan fitur lanjutan.
Bagaimana cara membandingkan folder java?
Muat dua path direktori, konfigurasikan opsi perbandingan, dan panggil API. Dalam tiga baris saja Anda dapat menghasilkan laporan HTML lengkap yang mencantumkan setiap file yang ditambahkan, dihapus, atau dimodifikasi.
Comparison comparison = new Comparison();
comparison.compare("C:/Project/v1", "C:/Project/v2", "C:/Reports/diff.html");
Metode compare memindai kedua folder secara rekursif, mencocokkan file berdasarkan nama, dan menulis laporan HTML visual ke lokasi target. Laporan menyoroti perubahan baris‑per‑baris untuk file berbasis teks serta menampilkan pratinjau berdampingan untuk gambar dan PDF.
Kelas Comparison adalah titik masuk API utama yang melakukan perbandingan direktori dan menghasilkan laporan.
Bungkus pemanggilan dalam blok try‑with‑resources (atau gunakan metode close pada objek Comparison) untuk memastikan semua handle file dilepaskan segera, terutama saat memproses ribuan file.
Opsi konfigurasi lanjutan
Penyiapan dasar cukup untuk kebanyakan skenario, namun proyek dunia nyata sering memerlukan perilaku yang disesuaikan.
Menyesuaikan format output
GroupDocs.Comparison dapat mengekspor laporan sebagai PDF, DOCX, atau HTML biasa. Mengganti format cukup dengan mengubah ekstensi file pada pemanggilan compare.
Memfilter file dan direktori
Jika Anda hanya peduli pada tipe file tertentu (misalnya .java dan .xml), sediakan predikat filter untuk melewatkan file yang tidak relevan dan secara dramatis meningkatkan kinerja.
comparison.setFileFilter(path -> path.toString().endsWith(".java") || path.toString().endsWith(".xml"));
Masalah umum dan solusinya
Mari bahas masalah yang kemungkinan akan Anda temui (karena hukum Murphy juga berlaku untuk pemrograman).
Masalah 1: OutOfMemoryError dengan direktori besar
Jawaban langsung: Tingkatkan ukuran heap JVM (-Xmx4g atau lebih) dan aktifkan mode streaming pada opsi Comparison untuk memproses file secara berurutan alih‑alih memuat semuanya ke memori.
Saat menangani direktori berisi puluhan ribu file, pendekatan default yang memuat seluruh data ke memori dapat melampaui heap. Mode streaming membaca setiap file saat dibutuhkan, menjaga jejak memori di bawah 200 MB bahkan untuk proses 10.000 file.
Masalah 2: FileNotFoundException meskipun path sudah benar
Jawaban langsung: Pastikan proses Java memiliki izin baca untuk direktori sumber dan izin tulis untuk folder output; juga pastikan spasi atau karakter khusus dalam path telah di‑escape dengan benar.
Penyebab umum meliputi pembatasan ACL tingkat OS, share jaringan yang memerlukan autentikasi, dan karakter Unicode yang perlu penanganan eksplisit via java.nio.file.Paths.
Masalah 3: Perbandingan memakan waktu lama
Jawaban langsung: Terapkan filter file untuk mengecualikan aset biner besar, aktifkan pemrosesan multi‑thread untuk sub‑folder yang independen, dan pantau kemajuan dengan listener callback untuk mengidentifikasi bottleneck lebih awal.
Paralelisasi perbandingan sub‑direktori dapat memotong waktu eksekusi hingga 70 % pada server 8‑core, sementara callback kemajuan memungkinkan Anda menampilkan progress bar sederhana di console untuk pekerjaan yang lama.
Optimasi kinerja untuk perbandingan skala besar
Ketika Anda menangani direktori dengan ribuan file, kinerja menjadi krusial. Berikut cara mengoptimalkannya:
Praktik terbaik manajemen memori
Kelas ComparisonOptions memungkinkan Anda mengatur perilaku proses perbandingan, seperti mengaktifkan mode streaming, menetapkan batas ukuran file, dan memilih format output.
- Aktifkan mode streaming (
ComparisonOptions.setUseStreaming(true)). - Batasi ukuran maksimum file yang diproses (
setMaxFileSize(200 * 1024 * 1024)untuk 200 MB). - Tutup objek
Comparisonsecara eksplisit setelah setiap run.
Strategi pemrosesan batch
Bagi pohon direktori besar menjadi batch logis (misalnya per modul atau per rentang tanggal) dan jalankan tiap batch secara berurutan. Ini mencegah JVM pernah memuat lebih dari satu batch sekaligus di memori.
Pemrosesan paralel untuk direktori independen
Jika Anda memiliki banyak pasangan direktori untuk dibandingkan (misalnya build malam untuk beberapa micro‑service), luncurkan instance Comparison terpisah dalam thread pool. Setiap thread bekerja pada pasangannya masing‑masing, memanfaatkan semua core CPU.
Kasus penggunaan dunia nyata dan aplikasi industri
Perbandingan direktori bukan hanya alat bagi developer — ia digunakan lintas industri untuk proses bisnis kritis:
Pengembangan perangkat lunak dan DevOps
Manajemen rilis: Bandingkan folder staging vs produksi sebelum deployment untuk menangkap drift konfigurasi. Laporan HTML dapat dilampirkan pada pull‑request untuk tinjauan pemangku kepentingan.
Keuangan dan kepatuhan
Pemeliharaan jejak audit: Institusi keuangan menggunakan perbandingan direktori untuk melacak perubahan dokumen demi kepatuhan regulasi, memastikan setiap amandemen tercatat dan diarsipkan.
Manajemen data dan proses ETL
Verifikasi integritas data: Setelah migrasi data massal, jalankan perbandingan folder untuk menjamin setiap file sumber berhasil dipindahkan ke data lake target.
Manajemen konten dan penerbitan
Kontrol versi untuk tim non‑teknis: Tim pemasaran dapat membandingkan dua versi folder aset situs web tanpa perlu pengetahuan Git, menerima diff visual yang jelas.
Tips lanjutan dan praktik terbaik
Setelah bekerja dengan perbandingan direktori di lingkungan produksi, berikut beberapa pelajaran penting:
Logging dan monitoring
Integrasikan SLF4J dengan appender file bergulir untuk merekam waktu mulai, waktu selesai, jumlah file yang diproses, dan pengecualian apa pun. Log ini menjadi sangat berharga saat menyelidiki kegagalan intermiten.
Pemulihan error dan ketahanan
Bungkus pemanggilan compare dalam blok retry yang menangkap error I/O transien (misalnya gangguan jaringan pada drive yang dipasang) dan jalankan ulang perbandingan hingga tiga kali sebelum menghentikan.
Manajemen konfigurasi
Eksternalisasikan semua path, format output, dan flag kinerja ke dalam file application.yml atau properties. Ini memungkinkan tim operasi menyesuaikan pengaturan tanpa harus meng‑compile ulang JAR.
Penanganan path lintas platform
Selalu bangun path dengan java.nio.file.Paths.get(...) dan gunakan File.separator saat menggabungkan string. Ini menghindari bug saat berpindah dari Windows (\) ke Linux (/).
Mengabaikan timestamp ketika tidak relevan
Jika hanya perubahan konten yang penting, setel CompareOptions.setIgnoreMetadata(true). Ini mencegah false positive yang disebabkan oleh pembaruan timestamp otomatis pada file yang disalin.
Memecahkan masalah umum pada deployment
Berjalan di development, gagal di production
Jawaban langsung: Periksa perbedaan sensitivitas huruf (Windows vs Linux), verifikasi izin sistem file, dan ganti pemisah path yang hard‑coded dengan File.separator.
Server produksi biasanya berjalan di Linux, di mana myFile.txt dan MyFile.txt dianggap berbeda. Gunakan API Path untuk menormalkan case dan menghindari ketidaksesuaian tidak sengaja.
Hasil tidak konsisten
Jawaban langsung: Pastikan tidak ada proses eksternal yang memodifikasi file selama run perbandingan, dan konfigurasikan CompareOptions untuk mengabaikan timestamp jika menyebabkan perbedaan palsu.
Menjalankan perbandingan pada snapshot read‑only (misalnya volume snapshot yang dipasang) menjamin hasil yang deterministik.
Pertanyaan yang sering diajukan
T: Bagaimana cara menangani direktori dengan jutaan file?
J: Gabungkan pemrosesan batch, tingkatkan heap JVM (-Xmx8g atau lebih), aktifkan mode streaming, dan jalankan perbandingan sub‑direktori secara paralel. Bagian Strategi Pemrosesan Batch dan Pemrosesan Paralel menyediakan pola siap pakai.
T: Bisakah saya membandingkan direktori yang berada di server berbeda?
J: Ya, tetapi latensi jaringan mendominasi waktu eksekusi. Untuk kinerja terbaik, salin direktori remote ke lokal terlebih dahulu atau mount share remote dengan bandwidth I/O yang cukup sebelum memanggil perbandingan.
T: Format file apa saja yang didukung oleh GroupDocs.Comparison?
J: GroupDocs.Comparison mendukung lebih dari 70 format, termasuk DOC/DOCX, PDF, PPT/PPTX, XLS/XLSX, TXT, HTML, XML, CSV, serta tipe gambar umum (PNG, JPEG, BMP). Lihat dokumentasi resmi untuk daftar terbaru.
T: Bagaimana saya dapat mengintegrasikan perbandingan ini ke dalam pipeline CI/CD?
J: Paketkan logika perbandingan ke dalam JAR yang dapat dijalankan atau plugin Maven, lalu panggil sebagai langkah build di Jenkins, GitHub Actions, Azure Pipelines, atau GitLab CI. Ekspor laporan HTML sebagai artefak build untuk ditinjau selanjutnya.
T: Apakah memungkinkan menyesuaikan tampilan laporan HTML?
J: Template HTML bawaan bersifat tetap, namun Anda dapat memproses file yang dihasilkan—menyuntikkan CSS atau JavaScript khusus—untuk menyesuaikan branding perusahaan atau menambahkan elemen interaktif.
Terakhir diperbarui: 2026-08-09
Diuji dengan: GroupDocs.Comparison 25.2 (Java)
Penulis: GroupDocs
<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>
import com.groupdocs.comparison.Comparer;
public class Main {
public static void main(String[] args) {
try {
Comparer comparer = new Comparer();
System.out.println("GroupDocs.Comparison initialized successfully!");
} catch (Exception e) {
System.err.println("Setup issue: " + e.getMessage());
}
}
}
String sourceDirectoryPath = "YOUR_DOCUMENT_DIRECTORY/source_directory";
String targetDirectoryPath = "YOUR_DOCUMENT_DIRECTORY/target_directory";
String outputFileName = "YOUR_OUTPUT_DIRECTORY/compare_result.html";
import com.groupdocs.comparison.options.CompareOptions;
import com.groupdocs.comparison.options.enums.FolderComparisonExtension;
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
compareOptions.setFolderComparisonExtension(FolderComparisonExtension.HTML);
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
comparer.add(targetDirectoryPath, compareOptions);
comparer.compareDirectory(outputFileName, compareOptions);
System.out.println("Directory comparison completed. Results saved to: " + outputFileName);
} catch (Exception e) {
System.err.println("Comparison failed: " + e.getMessage());
e.printStackTrace();
}
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// HTML for human review
compareOptions.setFolderComparisonExtension(FolderComparisonExtension.HTML);
// Or PDF for formal reports
// compareOptions.setFolderComparisonExtension(FolderComparisonExtension.PDF);
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// Skip temporary files and build directories
// Note: Exact filtering syntax may vary - check current API documentation
compareOptions.setShowDeletedContent(false); // Don't highlight deleted files
compareOptions.setShowInsertedContent(true); // Do highlight new files
// JVM args: -Xmx4g -Xms2g
// For very large directories, consider processing subdirectories separately
String[] subdirectories = {"subdir1", "subdir2", "subdir3"};
for (String subdir : subdirectories) {
String sourceSub = sourceDirectoryPath + "/" + subdir;
String targetSub = targetDirectoryPath + "/" + subdir;
// Process each subdirectory individually
}
// Better path handling
Path sourcePath = Paths.get(sourceDirectoryPath).toAbsolutePath();
Path targetPath = Paths.get(targetDirectoryPath).toAbsolutePath();
if (!Files.exists(sourcePath)) {
throw new IllegalArgumentException("Source directory doesn't exist: " + sourcePath);
}
if (!Files.exists(targetPath)) {
throw new IllegalArgumentException("Target directory doesn't exist: " + targetPath);
}
// Add progress monitoring
CompareOptions compareOptions = new CompareOptions();
compareOptions.setDirectoryCompare(true);
// Log progress (pseudo-code - actual implementation may vary)
long startTime = System.currentTimeMillis();
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
comparer.add(targetDirectoryPath, compareOptions);
comparer.compareDirectory(outputFileName, compareOptions);
long duration = System.currentTimeMillis() - startTime;
System.out.println("Comparison completed in: " + (duration / 1000) + " seconds");
}
// Increase heap size via JVM arguments
// -Xmx8g (for 8GB max heap)
// -XX:+UseG1GC (for better garbage collection with large heaps)
// In your code, help the GC by nulling large objects
CompareOptions compareOptions = new CompareOptions();
try (Comparer comparer = new Comparer(sourceDirectoryPath, compareOptions)) {
// ... do comparison
comparer.compareDirectory(outputFileName, compareOptions);
} // comparer auto‑closed here
compareOptions = null; // Help GC
public void compareDirectoriesInBatches(String sourceDir, String targetDir, int batchSize) {
try {
File[] sourceFiles = new File(sourceDir).listFiles();
if (sourceFiles != null) {
for (int i = 0; i < sourceFiles.length; i += batchSize) {
int end = Math.min(i + batchSize, sourceFiles.length);
processBatch(sourceFiles, i, end, targetDir);
// Optional: pause between batches to prevent system overload
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Batch processing interrupted", e);
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<String>> futures = new ArrayList<>();
for (DirectoryPair pair : directoryPairs) {
Future<String> future = executor.submit(() -> {
// Perform comparison for this pair
return compareDirectoryPair(pair.source, pair.target);
});
futures.add(future);
}
// Wait for all comparisons to complete
for (Future<String> future : futures) {
try {
String result = future.get();
System.out.println("Comparison result: " + result);
} catch (Exception e) {
System.err.println("Comparison failed: " + e.getMessage());
}
}
executor.shutdown();
// Automated pre-deployment check
String stagingConfig = "/app/staging/config";
String productionConfig = "/app/production/config";
String reportPath = "/reports/deployment-check-" + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE) + ".html";
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
options.setFolderComparisonExtension(FolderComparisonExtension.HTML);
try (Comparer comparer = new Comparer(stagingConfig, options)) {
comparer.add(productionConfig, options);
comparer.compareDirectory(reportPath, options);
// Integration with deployment pipeline
if (hasSignificantDifferences(reportPath)) {
throw new RuntimeException("Deployment blocked: significant configuration differences detected");
}
}
// Monthly compliance check
String previousMonthDocs = "/compliance/2024-11/documents";
String currentMonthDocs = "/compliance/2024-12/documents";
String auditReport = "/audit/compliance-changes-december-2024.html";
// Compare and generate audit‑ready reports
performComplianceComparison(previousMonthDocs, currentMonthDocs, auditReport);
public boolean verifyDataMigration(String sourceDataDir, String migratedDataDir) {
try {
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
String tempReport = "/tmp/migration-verification.html";
try (Comparer comparer = new Comparer(sourceDataDir, options)) {
comparer.add(migratedDataDir, options);
comparer.compareDirectory(tempReport, options);
}
// Custom logic to parse results and determine if migration was successful
return analyzeComparisonResults(tempReport);
} catch (Exception e) {
System.err.println("Migration verification failed: " + e.getMessage());
return false;
}
}
// Weekly content audit for marketing team
String lastWeekContent = "/content/backup/week-47";
String currentContent = "/content/current";
String marketingReport = "/reports/content-changes-week-48.html";
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
options.setFolderComparisonExtension(FolderComparisonExtension.HTML);
// Generate human‑readable report for non‑technical stakeholders
generateContentChangeReport(lastWeekContent, currentContent, marketingReport, options);
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(DirectoryComparer.class);
public void compareWithLogging(String source, String target, String output) {
logger.info("Starting directory comparison: {} vs {}", source, target);
long startTime = System.currentTimeMillis();
try {
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
try (Comparer comparer = new Comparer(source, options)) {
comparer.add(target, options);
comparer.compareDirectory(output, options);
}
long duration = System.currentTimeMillis() - startTime;
logger.info("Comparison completed successfully in {}ms. Report: {}", duration, output);
} catch (Exception e) {
logger.error("Directory comparison failed for {} vs {}: {}", source, target, e.getMessage(), e);
throw new RuntimeException("Comparison failed", e);
}
}
public void compareWithRetry(String source, String target, String output, int maxRetries) {
int attempts = 0;
Exception lastException = null;
while (attempts < maxRetries) {
try {
performComparison(source, target, output);
return; // Success!
} catch (Exception e) {
lastException = e;
attempts++;
if (attempts < maxRetries) {
try {
Thread.sleep(1000 * attempts); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Retry interrupted", ie);
}
}
}
}
throw new RuntimeException("Comparison failed after " + maxRetries + " attempts", lastException);
}
// application.properties
comparison.output.format=HTML
comparison.max.retries=3
comparison.batch.size=100
comparison.parallel.threads=4
// In your code
@Value("${comparison.output.format:HTML}")
private String outputFormat;
@Value("${comparison.max.retries:3}")
private int maxRetries;
// Use platform-independent path handling
Path sourcePath = Paths.get(sourceDirectory);
Path targetPath = Paths.get(targetDirectory);
Path outputPath = Paths.get(outputDirectory);
// Validate permissions before starting
if (!Files.isReadable(sourcePath)) {
throw new IllegalStateException("Cannot read source directory: " + sourcePath);
}
if (!Files.isReadable(targetPath)) {
throw new IllegalStateException("Cannot read target directory: " + targetPath);
}
if (!Files.isWritable(outputPath.getParent())) {
throw new IllegalStateException("Cannot write to output directory: " + outputPath.getParent());
}
CompareOptions options = new CompareOptions();
options.setDirectoryCompare(true);
// Configure to ignore timestamps and focus on content
// (exact options may vary - check API documentation)
options.setIgnoreWhitespaces(true);
options.setIgnoreFormatting(true);