Vergelijk mappen java – handleiding met GroupDocs.Comparison
Heb je ooit uren besteed aan handmatig controleren welke bestanden zijn gewijzigd tussen twee projectversies? Je bent niet de enige. GroupDocs.Comparison for Java maakt deze saaie taak een fluitje van een cent door je twee mappen te laten vergelijken met één API‑aanroep. In deze tutorial leer je hoe je compare folders java effectief kunt gebruiken, van de eerste installatie tot geavanceerde prestatie‑afstemming voor enorme codebases.
GroupDocs.Comparison for Java is a library that enables programmatic comparison of documents and directories. Het ondersteunt meer dan 70 invoer‑ en uitvoerformaten en kan mappen met tot 10.000 bestanden verwerken zonder de volledige bestandset in het geheugen te laden, waardoor het een robuuste keuze is voor audits op ondernemingsniveau.
Snelle antwoorden
- Wat is de primaire bibliotheek?
groupdocs comparison java - Ondersteunde Java‑versie? Java 8 of hoger
- Typische installatietijd? 10–15 minuten voor een basisvergelijking
- Licentie‑vereiste? Ja – een proef‑ of commerciële licentie is nodig
- Uitvoerformaten? HTML (standaard) of PDF
Wat is compare folders java?
De uitdrukking “compare folders java” verwijst naar het gebruik van een Java‑gebaseerde API om verschillen — toegevoegde, verwijderde of gewijzigde bestanden — tussen twee directory‑bomen te detecteren. GroupDocs.Comparison biedt een high‑level, besturingssysteem‑agnostische manier om deze bewerking uit te voeren, en retourneert een gedetailleerd HTML‑ of PDF‑rapport dat elke wijziging markeert.
Waarom compare folders java belangrijk is (meer dan je denkt)
Directory‑vergelijking gaat niet alleen over het opsporen van ontbrekende bestanden; het is een cruciaal controlepunt voor gegevensintegriteit, regelgeving‑naleving en release‑stabiliteit. Door het proces te automatiseren elimineer je menselijke fouten, versnel je audits en verkrijg je een enkele bron van waarheid die kan worden gearchiveerd voor toekomstig gebruik.
Gekwantificeerde voordelen
- Snelheid: Verwerkt mappen met 5.000 bestanden in minder dan 30 seconden op een typische 8‑core server.
- Dekbaarheid: Detecteert wijzigingen in meer dan 70 documenttypen, van DOCX tot PNG.
- Schaalbaarheid: Verwerkt bestanden tot 2 GB elk zonder de JVM‑heap uit te putten wanneer streaming‑modus is geconfigureerd.
- Nauwkeurigheid: Rapporteert verschillen met 99,9 % getrouwheid, behoud van lay‑out, tabellen en afbeeldingen.
Voorvereisten en installatie‑vereisten
Voordat we beginnen met coderen, zorg ervoor dat je omgeving klaar is. Dit is wat je nodig hebt (en waarom):
Essentiële vereisten
- Java 8 of hoger – GroupDocs.Comparison gebruikt moderne taalfeatures en API’s.
- Maven 3.6+ – Voor betrouwbare afhankelijkheidsresolutie; handmatig JAR‑beheer is foutgevoelig.
- IDE met goede Java‑ondersteuning – IntelliJ IDEA of Eclipse worden aanbevolen voor debugging en refactoring.
- Minimaal 2 GB RAM – Grote mapvergelijkingen kunnen veel geheugen verbruiken, vooral bij het genereren van HTML‑rapporten.
Vereiste kennis
- Basis Java‑syntaxis (lussen, exception‑handling, try‑with‑resources).
- Vertrouwdheid met bestands‑I/O (
java.nio.file.Path,FilesAPI). - Begrip van Maven’s
<dependency>‑ en<repository>‑secties.
Optioneel maar nuttig
- Ervaring met SLF4J/Logback voor logging.
- Kennis van multi‑threading concepten als je van plan bent vergelijkingen te paralleliseren.
- Basiskennis van HTML voor het aanpassen van het gegenereerde rapport.
Installatie van GroupDocs.Comparison voor Java
Laten we deze bibliotheek correct integreren in je project. De installatie is eenvoudig, maar er zijn een paar valkuilen om op te letten.
Maven‑configuratie
Voeg de volgende afhankelijkheid en repository toe aan je pom.xml. Vervang de versie‑placeholder door het nieuwste release‑nummer van de officiële GroupDocs‑site.
<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>
Pro tip: Controleer altijd het versienummer op de product‑downloadpagina; nieuwere releases bevatten prestatie‑patches en extra formaatondersteuning.
Licentie‑instelling (sla dit niet over)
GroupDocs is niet gratis, maar ze bieden verschillende licentie‑opties:
- Gratis proefversie: 30‑daagse proef met volledige functionaliteit — perfect voor evaluatie.
- Tijdelijke licentie: Uitgebreide proef voor ontwikkelings‑ en testomgevingen.
- Commerciële licentie: Vereist voor productie‑implementaties.
Haal uw licentie op via:
- Koop een licentie voor productie
- Ontvang een tijdelijke licentie voor uitgebreid testen
Basisinitialisatie en testen
Zodra je Maven‑build slaagt, maak je een eenvoudige testklasse die de licentie laadt en een minimale vergelijking uitvoert. Als het programma start zonder een uitzondering, is je omgeving correct geconfigureerd.
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.");
}
}
Als dit zonder fouten draait, kun je verder. Zo niet, controleer dan je Maven‑instellingen en zorg dat je machine de GroupDocs‑licentieserver kan bereiken.
Kernimplementatie: mapvergelijking
Nu het hoofdonderdeel — daadwerkelijk mappen vergelijken. We beginnen met een basisimplementatie en voegen daarna geavanceerde functies toe.
Hoe compare folders java?
Laad twee directory‑paden, configureer vergelijkingsopties en roep de API aan. In slechts drie regels kun je een volledig HTML‑diff‑rapport genereren dat elke toegevoegde, verwijderde of gewijzigde file opsomt.
Comparison comparison = new Comparison();
comparison.compare("C:/Project/v1", "C:/Project/v2", "C:/Reports/diff.html");
De compare‑methode scant beide mappen recursief, matcht bestanden op naam en schrijft een visueel HTML‑rapport naar de doel‑locatie. Het rapport markeert regel‑voor‑regel wijzigingen voor tekst‑gebaseerde bestanden en toont naast‑elkaar previews voor afbeeldingen en PDF’s.
De Comparison‑klasse is het primaire API‑ingangspunt dat de mapvergelijking uitvoert en het rapport genereert.
Wrap de aanroep in een try‑with‑resources‑blok (of gebruik de Comparison‑object‑close‑methode) om ervoor te zorgen dat alle bestands‑handles direct worden vrijgegeven, vooral bij het verwerken van duizenden bestanden.
Geavanceerde configuratie‑opties
De basisinstelling werkt voor de meeste scenario’s, maar real‑world projecten vereisen vaak fijn afgestelde gedragingen.
Aanpassen van uitvoerformaten
GroupDocs.Comparison kan rapporten exporteren als PDF, DOCX of platte HTML. Het wisselen van formaat is zo simpel als het wijzigen van de bestandsextensie in de compare‑aanroep.
Bestanden en mappen filteren
Als je alleen geïnteresseerd bent in specifieke bestandstypen (bijv. .java en .xml), geef dan een filter‑predicate op om irrelevante bestanden over te slaan en de prestaties dramatisch te verbeteren.
comparison.setFileFilter(path -> path.toString().endsWith(".java") || path.toString().endsWith(".xml"));
Veelvoorkomende problemen en oplossingen
Laten we de problemen behandelen die je waarschijnlijk tegenkomt (want Murphy’s Law geldt ook voor code).
Probleem 1: OutOfMemoryError bij grote mappen
Direct antwoord: Verhoog de JVM‑heap‑grootte (-Xmx4g of hoger) en schakel streaming‑modus in de Comparison‑opties in om bestanden sequentieel te verwerken in plaats van ze allemaal in het geheugen te laden.
Bij mappen met tienduizenden bestanden kan de standaard in‑memory‑aanpak de heap overschrijden. Streaming‑modus leest elk bestand on‑demand, waardoor de geheugenvoetafdruk onder 200 MB blijft, zelfs bij runs met 10.000 bestanden.
Probleem 2: FileNotFoundException ondanks correcte paden
Direct antwoord: Controleer of het Java‑proces leesrechten heeft voor de bron‑mappen en schrijfrechten voor de output‑map; zorg er ook voor dat eventuele spaties of speciale tekens in het pad correct zijn geescaped.
Veelvoorkomende oorzaken zijn OS‑niveau ACL‑beperkingen, netwerkschijven die authenticatie vereisen, en Unicode‑tekens die expliciete handling via java.nio.file.Paths nodig hebben.
Probleem 3: Vergelijking duurt eeuwig
Direct antwoord: Pas bestandsfilters toe om grote binaire assets uit te sluiten, schakel multi‑threaded verwerking in voor onafhankelijke sub‑mappen, en monitor de voortgang met een callback‑listener om knelpunten vroegtijdig te identificeren.
Paralleliseren van sub‑directory‑vergelijkingen kan de runtime tot 70 % verkorten op een 8‑core server, terwijl voortgangs‑callbacks je een eenvoudige console‑progressiebalk laten zien voor langdurige taken.
Prestatie‑optimalisatie voor grootschalige vergelijkingen
Wanneer je werkt met mappen die duizenden bestanden bevatten, wordt prestatie cruciaal. Zo optimaliseer je:
Best practices voor geheugenbeheer
De ComparisonOptions‑klasse laat je het gedrag van het vergelijkingsproces configureren, zoals het inschakelen van streaming‑modus, het instellen van bestands‑grootte‑limieten en het kiezen van uitvoerformaten.
- Gebruik streaming‑modus (
ComparisonOptions.setUseStreaming(true)). - Beperk de maximale bestandsgrootte die wordt verwerkt (
setMaxFileSize(200 * 1024 * 1024)) voor 200 MB. - Sluit het
Comparison‑object expliciet na elke uitvoering.
Batch‑verwerkingsstrategie
Splits een enorme directory‑boom op in logische batches (bijv. per module of per datumbereik) en voer elke batch opeenvolgend uit. Dit voorkomt dat de JVM ooit meer dan één batch tegelijk in het geheugen houdt.
Parallel verwerken voor onafhankelijke mappen
Als je meerdere map‑paren moet vergelijken (bijv. nacht‑builds voor verschillende micro‑services), start dan afzonderlijke Comparison‑instanties in een thread‑pool. Elke thread werkt aan zijn eigen paar, waardoor alle CPU‑kernen worden benut.
Praktijkvoorbeelden en industriële toepassingen
Directory‑vergelijking is niet alleen een ontwikkelaarstool — het wordt in diverse sectoren gebruikt voor bedrijfskritische processen:
Softwareontwikkeling en DevOps
Release‑beheer: Vergelijk staging‑ versus productie‑mappen vóór deployment om configuratie‑drift te detecteren. Het HTML‑rapport kan aan een pull‑request worden toegevoegd voor stakeholder‑review.
Financiën en compliance
Audit‑trail onderhoud: Financiële instellingen gebruiken directory‑vergelijking om documentwijzigingen bij te houden voor regelgeving‑naleving, zodat elke wijziging wordt gelogd en gearchiveerd.
Gegevensbeheer en ETL‑processen
Gegevensintegriteit verificatie: Na een bulk‑datamigratie kun je een map‑vergelijking uitvoeren om te garanderen dat elk bronbestand correct is aangekomen in de doel‑data‑lake.
Contentbeheer en publicatie
Versiebeheer voor niet‑technische teams: Marketingteams kunnen twee versies van een website‑asset‑map vergelijken zonder Git‑kennis, met een duidelijk visueel diff‑rapport.
Geavanceerde tips en best practices
Na het werken met directory‑vergelijking in productie‑omgevingen, hier enkele hard‑geleerde lessen:
Logging en monitoring
Integreer SLF4J met een rolling‑file‑appender om start‑tijd, eind‑tijd, verwerkt‑bestand‑aantal en eventuele uitzonderingen vast te leggen. Dit logboek is van onschatbare waarde bij het onderzoeken van intermitterende fouten.
Foutherstel en veerkracht
Wrap de compare‑aanroep in een retry‑blok dat tijdelijke I/O‑fouten (bijv. netwerk‑haperingen op gemonteerde schijven) opvangt en de vergelijking tot drie keer opnieuw uitvoert voordat hij afbreekt.
Configuratiebeheer
Externaliseer alle paden, uitvoerformaten en prestatie‑vlaggen in een application.yml‑ of properties‑bestand. Hierdoor kunnen operationele teams instellingen aanpassen zonder de JAR opnieuw te compileren.
Platformonafhankelijke padafhandeling
Bouw paden altijd op met java.nio.file.Paths.get(...) en gebruik File.separator bij het samenvoegen van strings. Dit voorkomt bugs bij migratie van Windows (\) naar Linux (/) omgevingen.
Tijdstempels negeren wanneer ze niet relevant zijn
Als alleen inhouds‑wijzigingen van belang zijn, stel CompareOptions.setIgnoreMetadata(true) in. Dit voorkomt valse positieven veroorzaakt door automatische tijdstempel‑updates bij gekopieerde bestanden.
Problemen oplossen bij veelvoorkomende implementatie‑issues
Werkt in ontwikkeling, faalt in productie
Direct antwoord: Controleer op case‑sensitivity verschillen (Windows vs Linux), verifieer bestands‑systeem‑rechten, en vervang hard‑gecodeerde pad‑scheidingstekens door File.separator.
Productieservers draaien vaak op Linux, waar myFile.txt en MyFile.txt verschillend zijn. Gebruik Path‑API’s om case te normaliseren en onbedoelde mismatches te vermijden.
Inconsistente resultaten
Direct antwoord: Zorg dat er geen extern proces bestanden wijzigt tijdens de vergelijking, en configureer CompareOptions om tijdstempels te negeren als ze valse verschillen veroorzaken.
Het uitvoeren van de vergelijking op een read‑only snapshot (bijv. een gemonteerde volumesnapshot) garandeert deterministische resultaten.
Veelgestelde vragen
Q: Hoe ga ik om met mappen die miljoenen bestanden bevatten?
A: Combineer batch‑verwerking, vergroot de JVM‑heap (-Xmx8g of hoger), schakel streaming‑modus in, en voer sub‑directory‑vergelijkingen parallel uit. De secties Batch‑verwerkingsstrategie en Parallel verwerken bieden kant‑klaar‑patronen.
Q: Kan ik mappen vergelijken die zich op verschillende servers bevinden?
A: Ja, maar netwerk‑latentie domineert de runtime. Voor optimale prestaties kopieer je de externe map eerst lokaal of mount je de remote share met voldoende I/O‑bandbreedte voordat je de vergelijking aanroept.
Q: Welke bestandsformaten ondersteunt GroupDocs.Comparison?
A: GroupDocs.Comparison ondersteunt meer dan 70 formaten, inclusief DOC/DOCX, PDF, PPT/PPTX, XLS/XLSX, TXT, HTML, XML, CSV en gangbare afbeeldingsformaten (PNG, JPEG, BMP). Zie de officiële documentatie voor de meest actuele lijst.
Q: Hoe kan ik deze vergelijking integreren in een CI/CD‑pipeline?
A: Package de vergelijkingslogica in een uitvoerbare JAR of Maven‑plugin, roep deze vervolgens aan als een build‑stap in Jenkins, GitHub Actions, Azure Pipelines of GitLab CI. Exporteer het HTML‑rapport als een build‑artefact voor downstream review.
Q: Is het mogelijk het uiterlijk van het HTML‑rapport aan te passen?
A: Het ingebouwde HTML‑template is vast, maar je kunt het gegenereerde bestand post‑processen — aangepaste CSS of JavaScript injecteren — om het te laten overeenkomen met je corporate branding of interactieve elementen toe te voegen.
Laatst bijgewerkt: 2026-08-09
Getest met: GroupDocs.Comparison 25.2 (Java)
Auteur: 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);