Klasörleri karşılaştırma java – GroupDocs.Comparison kullanarak rehber
İki proje sürümü arasında hangi dosyaların değiştiğini manuel olarak saatlerce kontrol ettiniz mi? Yalnız değilsiniz. GroupDocs.Comparison for Java tek bir API çağrısı ile iki klasörü karşılaştırmanıza olanak tanıyarak bu zahmetli görevi çok kolaylaştırır. Bu öğreticide, compare folders java‘yu etkili bir şekilde nasıl yapacağınızı, başlangıç kurulumundan büyük kod tabanları için gelişmiş performans ayarlarına kadar öğreneceksiniz.
GroupDocs.Comparison for Java, belgelerin ve dizinlerin programatik olarak karşılaştırılmasını sağlayan bir kütüphanedir. 70+ giriş ve çıkış formatını destekler ve tüm dosya setini belleğe yüklemeden 10.000 dosyaya kadar dizinleri işleyebilir, bu da onu kurumsal ölçekli denetimler için sağlam bir seçim yapar.
Hızlı yanıtlar
- Ana kütüphane nedir?
groupdocs comparison java - Desteklenen Java sürümü? Java 8 or higher
- Tipik kurulum süresi? 10–15 minutes for a basic comparison
- Lisans gereksinimi? Yes – a trial or commercial license is needed
- Çıktı formatları? HTML (default) or PDF
compare folders java nedir?
“compare folders java” ifadesi, iki dizin ağacı arasındaki farkları (eklenen, kaldırılan veya değiştirilmiş dosyalar) tespit etmek için Java tabanlı bir API kullanmayı ifade eder. GroupDocs.Comparison, bu işlemi gerçekleştirmek için yüksek seviyeli, dosya sistemi bağımsız bir yol sunar ve her değişikliği vurgulayan ayrıntılı bir HTML veya PDF raporu döndürür.
compare folders java neden önemlidir (düşündüğünüzden daha fazla)
Dizin karşılaştırması sadece eksik dosyaları bulmakla ilgili değildir; veri bütünlüğü, düzenleyici uyumluluk ve sürüm kararlılığı için kritik bir kontrol noktasıdır. Süreci otomatikleştirerek insan hatasını ortadan kaldırır, denetimleri hızlandırır ve gelecekte referans alınabilecek tek bir gerçek kaynağı elde edersiniz.
Ölçülen faydalar
- Speed: Processes 5,000‑file directories in under 30 seconds on a typical 8‑core server.
- Coverage: Detects changes across 70+ document types, from DOCX to PNG.
- Scalability: Handles files up to 2 GB each without exhausting JVM heap when configured with streaming mode.
- Accuracy: Reports differences with 99.9 % fidelity, preserving layout, tables, and images.
Önkoşullar ve kurulum gereksinimleri
Kodlamaya başlamadan önce ortamınızın hazır olduğundan emin olun. İşte ihtiyacınız olanlar (ve nedenleri):
Temel gereksinimler
- Java 8 or higher – GroupDocs.Comparison modern dil özellikleri ve API’leri kullanır.
- Maven 3.6+ – Güvenilir bağımlılık çözümü için; manuel JAR yönetimi hataya açıktır.
- IDE with good Java support – IntelliJ IDEA veya Eclipse, hata ayıklama ve yeniden düzenleme için önerilir.
- At least 2 GB RAM – Büyük dizin karşılaştırmaları önemli miktarda bellek tüketebilir, özellikle HTML raporları oluşturulurken.
Bilgi önkoşulları
- Basic Java syntax (loops, exception handling, try‑with‑resources).
- Familiarity with file I/O (
java.nio.file.Path,FilesAPI). - Understanding of Maven’s
<dependency>and<repository>sections.
Opsiyonel ancak faydalı
- Experience with SLF4J/Logback for logging.
- Knowledge of multi‑threading concepts if you plan to parallelise comparisons.
- Basic HTML knowledge for customizing the generated report.
GroupDocs.Comparison for Java kurulumu
Bu kütüphaneyi projenize düzgün bir şekilde entegre edelim. Kurulum basittir, ancak dikkat etmeniz gereken birkaç nokta vardır.
Maven yapılandırması
Aşağıdaki bağımlılığı ve depoyu pom.xml dosyanıza ekleyin. Versiyon yer tutucusunu resmi GroupDocs sitesindeki en son sürüm numarasıyla değiştirin.
<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>
İpucu: Versiyon numarasını ürün indirme sayfasında her zaman doğrulayın; yeni sürümler performans yamaları ve ek format desteği içerir.
Lisans kurulumu (bunu atlamayın)
GroupDocs ücretsiz değildir, ancak çeşitli lisans seçenekleri sunar:
- Free trial: 30‑day trial with full feature set—perfect for evaluation.
- Temporary license: Extended trial for development and testing environments.
- Commercial license: Required for production deployments.
Lisansınızı şu adreslerden alın:
- Purchase a license for production
- Get a temporary license for extended testing
Temel başlatma ve test
Maven derlemeniz başarılı olduğunda, lisansı yükleyen ve minimal bir karşılaştırma çalıştıran basit bir test sınıfı oluşturun. Program bir istisna atmadan başlarsa ortamınız doğru yapılandırılmış demektir.
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.");
}
}
Bu hatasız çalışıyorsa devam edebilirsiniz. Çalışmazsa Maven ayarlarınızı tekrar kontrol edin ve makinenizin GroupDocs lisans sunucusuna erişebildiğinden emin olun.
Temel uygulama: dizin karşılaştırması
Şimdi asıl olaya — dizinleri karşılaştırmaya. Temel bir uygulama ile başlayıp ardından gelişmiş özellikler ekleyeceğiz.
compare folders java nasıl yapılır?
İki dizin yolunu yükleyin, karşılaştırma seçeneklerini yapılandırın ve API’yi çağırın. Sadece üç satırda her eklenen, silinen veya değiştirilmiş dosyayı listeleyen tam bir HTML fark raporu oluşturabilirsiniz.
Comparison comparison = new Comparison();
comparison.compare("C:/Project/v1", "C:/Project/v2", "C:/Reports/diff.html");
compare metodu her iki klasörü de rekürsif olarak tarar, dosyaları isimlerine göre eşleştirir ve hedef konuma görsel bir HTML raporu yazar. Rapor, metin tabanlı dosyalar için satır‑satır değişiklikleri ve resim‑PDF dosyaları için yan‑yana ön izlemeleri gösterir.
Comparison sınıfı, dizin karşılaştırmasını gerçekleştiren ve raporu oluşturan birincil API giriş noktasıdır.
Kaynakları hızlı bir şekilde serbest bırakmak için çağrıyı try‑with‑resources bloğu içinde (veya Comparison nesnesinin close metodunu) sarmalayın, özellikle binlerce dosya işlenirken.
Gelişmiş yapılandırma seçenekleri
Temel kurulum çoğu senaryo için yeterlidir, ancak gerçek dünyadaki projeler genellikle ince ayar davranışı gerektirir.
Çıktı formatlarını özelleştirme
GroupDocs.Comparison raporları PDF, DOCX veya düz HTML olarak dışa aktarabilir. Formatı değiştirmek, compare çağrısındaki dosya uzantısını değiştirmek kadar basittir.
Dosya ve dizinleri filtreleme
Sadece belirli dosya türleri (ör. .java ve .xml) ile ilgileniyorsanız, ilgisiz dosyaları atlamak ve performansı büyük ölçüde artırmak için bir filtre önermesi sağlayın.
comparison.setFileFilter(path -> path.toString().endsWith(".java") || path.toString().endsWith(".xml"));
Yaygın sorunlar ve çözümler
Karşılaşmanız muhtemel problemleri ele alalım (çünkü Murphy Yasası kodlamaya da uygulanır).
Sorun 1: Büyük dizinlerde OutOfMemoryError
Doğrudan cevap: JVM heap boyutunu artırın (-Xmx4g veya daha yüksek) ve Comparison seçeneklerinde akış (streaming) modunu etkinleştirerek dosyaları belleğe tamamen yüklemek yerine sıralı olarak işleyin.
On binlerce dosya içeren dizinlerle çalışırken, varsayılan bellek içi yaklaşım heap’i aşabilir. Akış modu, her dosyayı gerektiğinde okur ve 10.000 dosyalık çalışmalarda bile bellek ayak izini 200 MB altında tutar.
Sorun 2: Doğru yollara rağmen FileNotFoundException
Doğrudan cevap: Java sürecinin kaynak dizinler için okuma, çıktı klasörü için yazma izinlerine sahip olduğundan emin olun; ayrıca yollardaki boşluklar veya özel karakterlerin doğru şekilde kaçırıldığını kontrol edin.
Yaygın nedenler arasında OS‑seviyesinde ACL kısıtlamaları, kimlik doğrulama gerektiren ağ paylaşımları ve Unicode karakterlerinin java.nio.file.Paths ile açıkça ele alınması bulunur.
Sorun 3: Karşılaştırma çok uzun sürüyor
Doğrudan cevap: Büyük ikili varlıkları dışlamak için dosya filtreleri uygulayın, bağımsız alt‑klasörler için çok‑iş parçacıklı (multi‑threaded) işleme etkinleştirin ve ilerlemeyi bir geri çağırma dinleyicisiyle izleyerek darboğazları erken tespit edin.
Alt‑dizin karşılaştırmalarını paralelleştirmek, 8‑çekirdekli bir sunucuda çalışma süresini %70’e kadar azaltabilir; ilerleme geri çağırıcıları uzun süren işler için basit bir konsol ilerleme çubuğu sunar.
Büyük ölçekli karşılaştırmalar için performans optimizasyonu
Binlerce dosya içeren dizinlerle uğraşırken performans kritik hale gelir. İşte nasıl optimize edileceği:
Bellek yönetimi en iyi uygulamaları
ComparisonOptions sınıfı, karşılaştırma sürecinin davranışını yapılandırmanıza izin verir; örneğin akış modunu etkinleştirme, dosya boyutu limitleri ayarlama ve çıktı formatlarını seçme gibi.
- Use streaming mode (
ComparisonOptions.setUseStreaming(true)). - Limit the maximum file size processed (
setMaxFileSize(200 * 1024 * 1024)for 200 MB). - Close the
Comparisonobject explicitly after each run.
Toplu işleme stratejisi
Büyük bir dizin ağacını mantıksal partiler halinde (ör. modül bazlı veya tarih aralığı bazlı) bölün ve her partiyi sıralı olarak çalıştırın. Bu, JVM’nin aynı anda bir partiden fazlasını bellekte tutmasını engeller.
Bağımsız dizinler için paralel işleme
Birden fazla dizin çifti karşılaştırmanız gerekiyorsa (ör. birkaç mikro‑servis için gece çalıştırmaları), bir iş parçacığı havuzunda ayrı Comparison örnekleri başlatın. Her iş parçacığı kendi çiftine odaklanarak tüm CPU çekirdeklerini kullanır.
Gerçek dünya kullanım durumları ve endüstri uygulamaları
Dizin karşılaştırması sadece bir geliştirici aracı değildir — işletme kritik süreçlerde de kullanılır:
Yazılım geliştirme ve DevOps
Release management: Dağıtımdan önce sahneleme vs üretim klasörlerini karşılaştırarak konfigürasyon kaymalarını yakalayın. HTML raporu, paydaş incelemesi için bir pull‑request’e eklenebilir.
Finans ve uyumluluk
Audit trail maintenance: Finans kurumları, düzenleyici uyumluluk için belge değişikliklerini izlemek amacıyla dizin karşılaştırması kullanır; her değişiklik kaydedilir ve arşivlenir.
Veri yönetimi ve ETL süreçleri
Data integrity verification: Toplu veri göçünden sonra, her kaynak dosyanın hedef veri gölüne doğru bir şekilde aktarıldığını garanti etmek için klasör karşılaştırması çalıştırın.
İçerik yönetimi ve yayıncılık
Version control for non‑technical teams: Pazarlama ekipleri, Git bilgisine ihtiyaç duymadan bir web sitesinin varlık klasörünün iki sürümünü karşılaştırabilir ve net bir görsel fark alır.
İleri ipuçları ve en iyi uygulamalar
Üretim ortamlarında dizin karşılaştırmasıyla çalıştıktan sonra edinilen bazı zorunlu dersler:
Günlükleme ve izleme
SLF4J’yi bir dönen dosya ekleyicisiyle entegre ederek başlangıç‑zamanı, bitiş‑zamanı, işlenen dosya sayısı ve olası istisnaları yakalayın. Bu günlük, aralıklı hataları araştırırken paha biçilmez olur.
Hata kurtarma ve dayanıklılık
compare çağrısını, geçici I/O hatalarını (ör. bağlanmış sürücülerdeki ağ kesintileri) yakalayan bir yeniden deneme bloğuna sarın ve iptal etmeden önce üç kez yeniden çalıştırın.
Konfigürasyon yönetimi
Tüm yolları, çıktı formatlarını ve performans bayraklarını bir application.yml veya properties dosyasına dışarı taşıyın. Bu, operasyon ekiplerinin JAR’ı yeniden derlemeden ayarları değiştirmesine olanak tanır.
Platform bağımsız yol işleme
java.nio.file.Paths.get(...) ile yolları her zaman oluşturun ve dize birleştirirken File.separator kullanın. Bu, Windows (\) ile Linux (/) ortamları arasında geçişte hataları önler.
Önemli olmadığında zaman damgalarını yok sayma
Sadece içerik değişiklikleri önemliyse, CompareOptions.setIgnoreMetadata(true) ayarını yapın. Bu, kopyalanan dosyalardaki otomatik zaman damgası güncellemelerinden kaynaklanan yanlış pozitifleri önler.
Yaygın dağıtım sorunlarının giderilmesi
Geliştirmede çalışıyor, üretimde başarısız oluyor
Doğrudan cevap: Büyük/küçük harf duyarlılığı farklarını (Windows vs Linux), dosya sistemi izinlerini kontrol edin ve sabit yol ayırıcılarını File.separator ile değiştirin.
Üretim sunucuları genellikle Linux çalıştırır; burada myFile.txt ve MyFile.txt farklıdır. Path API’lerini kullanarak durumu normalleştirin ve yanlış eşleşmeleri önleyin.
Tutarsız sonuçlar
Doğrudan cevap: Karşılaştırma çalışması sırasında dış bir sürecin dosyaları değiştirmediğinden emin olun ve zaman damgalarını göz ardı etmek için CompareOptions‘ı yapılandırın.
Okunabilir bir anlık görüntü (ör. bir bağlanmış hacim anlık görüntüsü) içinde karşılaştırma çalıştırmak, deterministik sonuçlar garantiler.
Sıkça sorulan sorular
Q: Milyonlarca dosya içeren dizinleri nasıl yönetebilirim?
A: Toplu işleme, JVM heap’ini artırma (-Xmx8g veya daha yüksek), akış modunu etkinleştirme ve alt‑dizin karşılaştırmalarını paralel çalıştırma kombinasyonunu kullanın. Toplu İşleme Stratejisi ve Paralel İşleme bölümleri hazır kalıplar sunar.
Q: Farklı sunucularda bulunan dizinleri karşılaştırabilir miyim?
A: Evet, ancak ağ gecikmesi çalışma süresini belirler. En iyi performans için önce uzak dizini yerel olarak kopyalayın veya karşılaştırmayı çağırmadan önce yeterli I/O bant genişliğine sahip bir ağ paylaşımını bağlayın.
Q: GroupDocs.Comparison hangi dosya formatlarını destekliyor?
A: GroupDocs.Comparison, DOC/DOCX, PDF, PPT/PPTX, XLS/XLSX, TXT, HTML, XML, CSV ve yaygın görüntü türleri (PNG, JPEG, BMP) dahil 70+ formatı destekler. En güncel liste için resmi dokümantasyona bakın.
Q: Bu karşılaştırmayı bir CI/CD pipeline’ına nasıl entegre edebilirim?
A: Karşılaştırma mantığını çalıştırılabilir bir JAR veya Maven eklentisi haline getirin, ardından Jenkins, GitHub Actions, Azure Pipelines veya GitLab CI içinde bir derleme adımı olarak çağırın. HTML raporunu sonraki inceleme için bir derleme artefaktı olarak dışa aktarın.
Q: HTML raporunun görünümünü özelleştirmek mümkün mü?
A: Yerleşik HTML şablonu sabittir, ancak oluşturulan dosyayı sonradan işleyerek — özel CSS veya JavaScript enjekte ederek — kurumsal markanıza uyacak şekilde veya etkileşimli öğeler ekleyecek şekilde özelleştirebilirsiniz.
Last Updated: 2026-08-09
Tested With: GroupDocs.Comparison 25.2 (Java)
Author: 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);