Comparar pastas java – guia usando GroupDocs.Comparison

Já passou horas verificando manualmente quais arquivos foram alterados entre duas versões de um projeto? Você não está sozinho. GroupDocs.Comparison for Java torna essa tarefa tediosa simples, permitindo comparar duas pastas com uma única chamada de API. Neste tutorial você aprenderá a compare folders java efetivamente, desde a configuração inicial até o ajuste avançado de desempenho para bases de código massivas.

GroupDocs.Comparison for Java é uma biblioteca que permite a comparação programática de documentos e diretórios. Ela suporta mais de 70 formatos de entrada e saída e pode processar diretórios com até 10.000 arquivos sem carregar todo o conjunto de arquivos na memória, tornando‑a uma escolha robusta para auditorias em escala empresarial.

Respostas rápidas

  • Qual é a biblioteca principal? groupdocs comparison java
  • Versão Java suportada? Java 8 ou superior
  • Tempo típico de configuração? 10–15 minutos para uma comparação básica
  • Requisitos de licença? Sim – é necessária uma licença de avaliação ou comercial
  • Formatos de saída? HTML (padrão) ou PDF

O que é compare folders java?

A expressão “compare folders java” refere‑se ao uso de uma API baseada em Java para detectar diferenças — arquivos adicionados, removidos ou modificados — entre duas árvores de diretórios. O GroupDocs.Comparison fornece uma maneira de alto nível, independente do sistema de arquivos, para executar esta operação, retornando um relatório detalhado em HTML ou PDF que destaca cada alteração.

Por que compare folders java importa (mais do que você imagina)

A comparação de diretórios não se trata apenas de identificar arquivos ausentes; é um ponto de controle crítico para a integridade dos dados, conformidade regulatória e estabilidade de lançamentos. Ao automatizar o processo, você elimina erros humanos, acelera auditorias e obtém uma única fonte de verdade que pode ser arquivada para referência futura.

Benefícios quantificados

  • Velocidade: Processa diretórios com 5.000 arquivos em menos de 30 segundos em um servidor típico de 8 núcleos.
  • Cobertura: Detecta alterações em mais de 70 tipos de documentos, de DOCX a PNG.
  • Escalabilidade: Lida com arquivos de até 2 GB cada sem esgotar o heap da JVM quando configurado com modo de streaming.
  • Precisão: Relata diferenças com 99,9 % de fidelidade, preservando layout, tabelas e imagens.

Pré‑requisitos e requisitos de configuração

Antes de começarmos a codificar, certifique‑se de que seu ambiente está pronto. Aqui está o que você precisará (e por quê):

Requisitos essenciais

  1. Java 8 ou superior – O GroupDocs.Comparison usa recursos modernos da linguagem e APIs.
  2. Maven 3.6+ – Para resolução confiável de dependências; o manuseio manual de JARs é propenso a erros.
  3. IDE com bom suporte a Java – IntelliJ IDEA ou Eclipse são recomendados para depuração e refatoração.
  4. Pelo menos 2 GB de RAM – Comparações de diretórios grandes podem consumir memória significativa, especialmente ao gerar relatórios HTML.

Pré‑requisitos de conhecimento

  • Sintaxe básica de Java (loops, tratamento de exceções, try‑with‑resources).
  • Familiaridade com I/O de arquivos (java.nio.file.Path, API Files).
  • Compreensão das seções <dependency> e <repository> do Maven.

Opcional, mas útil

  • Experiência com SLF4J/Logback para logging.
  • Conhecimento de conceitos de multithreading se você planeja paralelizar comparações.
  • Conhecimento básico de HTML para personalizar o relatório gerado.

Configurando GroupDocs.Comparison para Java

Vamos integrar esta biblioteca corretamente ao seu projeto. A configuração é simples, mas há algumas armadilhas a observar.

Configuração do Maven

Adicione a seguinte dependência e repositório ao seu pom.xml. Certifique‑se de substituir o placeholder de versão pelo número da última versão disponível no site oficial da 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>

Dica profissional: Sempre verifique o número da versão na página de download do produto; lançamentos mais recentes incluem correções de desempenho e suporte a formatos adicionais.

Configuração de licença (não pule esta etapa)

GroupDocs não é gratuito, mas oferece várias opções de licenciamento:

  • Teste gratuito: Avaliação de 30 dias com conjunto completo de recursos — perfeito para avaliação.
  • Licença temporária: Avaliação estendida para ambientes de desenvolvimento e teste.
  • Licença comercial: Necessária para implantações em produção.

Obtenha sua licença em:

Inicialização básica e teste

Depois que sua compilação Maven for bem‑sucedida, crie uma classe de teste simples que carregue a licença e execute uma comparação mínima. Se o programa iniciar sem lançar exceções, seu ambiente está configurado corretamente.

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.");
    }
}

Se isso for executado sem erros, você está pronto para prosseguir. Caso contrário, verifique novamente suas configurações do Maven e assegure‑se de que sua máquina pode alcançar o servidor de licenciamento da GroupDocs.

Implementação principal: comparação de diretórios

Agora vem o evento principal — comparar efetivamente diretórios. Começaremos com uma implementação básica e depois adicionaremos recursos avançados.

Como comparar pastas java?

Carregue dois caminhos de diretório, configure as opções de comparação e invoque a API. Em apenas três linhas você pode gerar um relatório completo de diff em HTML que lista cada arquivo adicionado, excluído ou modificado.

Comparison comparison = new Comparison();
comparison.compare("C:/Project/v1", "C:/Project/v2", "C:/Reports/diff.html");

O método compare escaneia ambas as pastas recursivamente, combina arquivos por nome e grava um relatório visual em HTML no local de destino. O relatório destaca alterações linha a linha para arquivos baseados em texto e mostra pré‑visualizações lado a lado para imagens e PDFs.

A classe Comparison é o ponto de entrada principal da API que realiza a comparação de diretórios e gera o relatório.

Envolva a chamada em um bloco try‑with‑resources (ou use o método close do objeto Comparison) para garantir que todos os manipuladores de arquivos sejam liberados rapidamente, especialmente ao processar milhares de arquivos.

Opções avançadas de configuração

A configuração básica funciona para a maioria dos cenários, mas projetos reais frequentemente precisam de comportamento ajustado.

Personalizando formatos de saída

O GroupDocs.Comparison pode exportar relatórios como PDF, DOCX ou HTML simples. Trocar de formato é tão simples quanto mudar a extensão do arquivo na chamada compare.

Filtrando arquivos e diretórios

Se você se importa apenas com tipos de arquivos específicos (por exemplo, .java e .xml), forneça um predicado de filtro para ignorar arquivos irrelevantes e melhorar drasticamente o desempenho.

comparison.setFileFilter(path -> path.toString().endsWith(".java") || path.toString().endsWith(".xml"));

Problemas comuns e soluções

Vamos abordar os problemas que você provavelmente encontrará (porque a Lei de Murphy também se aplica à programação).

Problema 1: OutOfMemoryError com diretórios grandes

Resposta direta: Aumente o tamanho do heap da JVM (-Xmx4g ou superior) e habilite o modo de streaming nas opções de Comparison para processar arquivos sequencialmente em vez de carregá‑los todos na memória.

Quando ao lidar com diretórios contendo dezenas de milhares de arquivos, a abordagem padrão em memória pode exceder o heap. O modo de streaming lê cada arquivo sob demanda, mantendo o consumo de memória abaixo de 200 MB mesmo em execuções com 10.000 arquivos.

Problema 2: FileNotFoundException apesar de caminhos corretos

Resposta direta: Verifique se o processo Java tem permissões de leitura para os diretórios de origem e permissões de gravação para a pasta de saída; também assegure‑se de que quaisquer espaços ou caracteres especiais no caminho estejam devidamente escapados.

Causas comuns incluem restrições de ACL ao nível do SO, compartilhamentos de rede que requerem autenticação e caracteres Unicode que precisam de tratamento explícito via java.nio.file.Paths.

Problema 3: A comparação leva muito tempo

Resposta direta: Aplique filtros de arquivos para excluir ativos binários grandes, habilite o processamento multithread para sub‑pastas independentes e monitore o progresso com um listener de callback para identificar gargalos cedo.

Paralelizar comparações de sub‑diretórios pode reduzir o tempo de execução em até 70 % em um servidor de 8 núcleos, enquanto callbacks de progresso permitem exibir uma barra de progresso simples no console para tarefas de longa duração.

Otimização de desempenho para comparações em larga escala

Quando você lida com diretórios contendo milhares de arquivos, o desempenho torna‑se crítico. Veja como otimizar:

Melhores práticas de gerenciamento de memória

A classe ComparisonOptions permite configurar o comportamento do processo de comparação, como habilitar o modo de streaming, definir limites de tamanho de arquivo e escolher formatos de saída.

  • Use streaming mode (ComparisonOptions.setUseStreaming(true)).
  • Limite o tamanho máximo de arquivo processado (setMaxFileSize(200 * 1024 * 1024) para 200 MB).
  • Feche o objeto Comparison explicitamente após cada execução.

Estratégia de processamento em lote

Divida uma árvore de diretórios massiva em lotes lógicos (por exemplo, por módulo ou por intervalo de datas) e execute cada lote sequencialmente. Isso impede que a JVM mantenha mais de um lote na memória.

Processamento paralelo para diretórios independentes

Se você tem vários pares de diretórios para comparar (por exemplo, builds noturnos de vários microsserviços), inicie instâncias separadas de Comparison em um pool de threads. Cada thread trabalha em seu próprio par, aproveitando todos os núcleos da CPU.

Casos de uso reais e aplicações industriais

A comparação de diretórios não é apenas uma ferramenta de desenvolvedor — é usada em diversos setores para processos críticos de negócios:

Desenvolvimento de software e DevOps

Gerenciamento de releases: Compare pastas de staging vs produção antes da implantação para detectar desvios de configuração. O relatório HTML pode ser anexado a um pull‑request para revisão das partes interessadas.

Finanças e conformidade

Manutenção de trilha de auditoria: Instituições financeiras usam a comparação de diretórios para rastrear alterações de documentos para conformidade regulatória, garantindo que cada alteração seja registrada e arquivada.

Gerenciamento de dados e processos ETL

Verificação de integridade de dados: Após uma migração massiva de dados, execute uma comparação de pastas para garantir que cada arquivo de origem tenha sido corretamente colocado no data lake de destino.

Gerenciamento de conteúdo e publicação

Controle de versão para equipes não técnicas: Equipes de marketing podem comparar duas versões da pasta de ativos de um site sem precisar de conhecimento em Git, recebendo um diff visual claro.

Dicas avançadas e melhores práticas

Depois de trabalhar com comparação de diretórios em ambientes de produção, aqui estão algumas lições aprendidas na prática:

Logging e monitoramento

Integre SLF4J com um appender de arquivo rotativo para capturar horário de início, horário de término, contagem de arquivos processados e quaisquer exceções. Esse log torna‑se indispensável ao investigar falhas intermitentes.

Recuperação de erros e resiliência

Envolva a chamada compare em um bloco de retry que capture erros transitórios de I/O (por exemplo, falhas de rede em unidades montadas) e reexecute a comparação até três vezes antes de abortar.

Gerenciamento de configuração

Externalize todos os caminhos, formatos de saída e flags de desempenho em um arquivo application.yml ou properties. Isso permite que as equipes de operações ajustem as configurações sem recompilar o JAR.

Manipulação de caminhos independente de plataforma

Sempre construa caminhos com java.nio.file.Paths.get(...) e use File.separator ao concatenar strings. Isso evita bugs ao migrar de ambientes Windows (\) para Linux (/).

Ignorando timestamps quando não importam

Se apenas alterações de conteúdo importam, defina CompareOptions.setIgnoreMetadata(true). Isso impede falsos positivos causados por atualizações automáticas de timestamps em arquivos copiados.

Solucionando problemas comuns de implantação

Funciona em desenvolvimento, falha em produção

Resposta direta: Verifique diferenças de sensibilidade a maiúsculas/minúsculas (Windows vs Linux), confirme permissões do sistema de arquivos e substitua separadores de caminho codificados manualmente por File.separator.

Servidores de produção geralmente rodam em Linux, onde myFile.txt e MyFile.txt são distintos. Use APIs Path para normalizar o caso e evitar incompatibilidades acidentais.

Resultados inconsistentes

Resposta direta: Garanta que nenhum processo externo modifique arquivos durante a execução da comparação e configure CompareOptions para ignorar timestamps se eles causarem diferenças espúrias.

Executar a comparação em um snapshot somente leitura (por exemplo, um snapshot de volume montado) garante resultados determinísticos.

Perguntas frequentes

Q: Como lidar com diretórios com milhões de arquivos?
A: Combine processamento em lote, aumente o heap da JVM (-Xmx8g ou superior), habilite o modo de streaming e execute comparações de sub‑diretórios em paralelo. As seções Estratégia de Processamento em Lote e Processamento Paralelo fornecem padrões prontos para uso.

Q: Posso comparar diretórios localizados em servidores diferentes?
A: Sim, mas a latência da rede domina o tempo de execução. Para melhor desempenho, copie o diretório remoto localmente primeiro ou monte o compartilhamento remoto com largura de banda de I/O suficiente antes de invocar a comparação.

Q: Quais formatos de arquivo são suportados pelo GroupDocs.Comparison?
A: O GroupDocs.Comparison suporta mais de 70 formatos, incluindo DOC/DOCX, PDF, PPT/PPTX, XLS/XLSX, TXT, HTML, XML, CSV e tipos de imagem comuns (PNG, JPEG, BMP). Consulte a documentação oficial para a lista mais recente.

Q: Como posso integrar esta comparação em um pipeline CI/CD?
A: Empacote a lógica de comparação em um JAR executável ou plugin Maven, então invoque‑a como uma etapa de build no Jenkins, GitHub Actions, Azure Pipelines ou GitLab CI. Exporte o relatório HTML como um artefato de build para revisão posterior.

Q: É possível personalizar a aparência do relatório HTML?
A: O modelo HTML embutido é fixo, mas você pode pós‑processar o arquivo gerado — injetar CSS ou JavaScript personalizados — para adequá‑lo à identidade visual da sua empresa ou adicionar elementos interativos.

Última atualização: 2026-08-09
Testado com: GroupDocs.Comparison 25.2 (Java)
Autor: 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);

Tutoriais Relacionados