Determine si dos archivos almacenan el mismo contenido

¿Cómo escribirías una función java boolean sameContent(Path file1,Path file2) que determina si las dos rutas dadas apuntan a archivos que almacenan el mismo contenido? Por supuesto, primero, verificaría si los tamaños de los archivos son los mismos. Esta es una condición necesaria para almacenar el mismo contenido. Pero luego me gustaría escuchar tus enfoques. Si los dos archivos están almacenados en el mismo disco duro (como en la mayoría de mis casos), probablemente no sea la mejor manera de saltar demasiadas veces entre las dos transmisiones.

Exactamente qué método FileUtils.contentEquals de Apache commons IO hace y api está aquí .

Pruebe algo como:

 File file1 = new File("file1.txt"); File file2 = new File("file2.txt"); boolean isTwoEqual = FileUtils.contentEquals(file1, file2); 

Realiza las siguientes comprobaciones antes de hacer la comparación:

  • existencia de ambos archivos
  • Ambos archivos que se pasan son de tipo de archivo y no de directorio.
  • la longitud en bytes no debe ser la misma.
  • Ambos son archivos diferentes y no son lo mismo.
  • Luego compara los contenidos.

Si no desea utilizar ninguna biblioteca externa, simplemente lea los archivos en matrices de bytes y compárelos (no funcionará antes de Java-7):

 byte[] f1 = Files.readAllBytes(file1); byte[] f2 = Files.readAllBytes(file2); 

mediante el uso de Arrays.equals .

Si los archivos son grandes, entonces, en lugar de leer todos los archivos en matrices, debe usar BufferedInputStream y leer los archivos por partes, como se explica aquí .

Si los archivos son pequeños, puede leer ambos en la memoria y comparar los conjuntos de bytes.

Si los archivos no son pequeños, puede calcular los valores hash de su contenido (por ejemplo, MD5 o SHA-1) uno después de otro y comparar los valores hash (pero esto deja una pequeña posibilidad de error), o puede comparar su contenido, pero para esto todavía tiene que leer las secuencias alternando.

Aquí hay un ejemplo:

 boolean sameContent(Path file1, Path file2) throws IOException { final long size = Files.size(file1); if (size != Files.size(file2)) return false; if (size < 4096) return Arrays.equals(Files.readAllBytes(file1), Files.readAllBytes(file2)); try (InputStream is1 = Files.newInputStream(file1); InputStream is2 = Files.newInputStream(file2)) { // Compare byte-by-byte. // Note that this can be sped up drastically by reading large chunks // (eg 16 KBs) but care must be taken as InputStream.read(byte[]) // does not neccessarily read a whole array! int data; while ((data = is1.read()) != -1) if (data != is2.read()) return false; } return true; } 

Esto debería ayudarte con tu problema:

 package test; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; public class CompareFileContents { public static void main(String[] args) throws IOException { File file1 = new File("test1.txt"); File file2 = new File("test2.txt"); File file3 = new File("test3.txt"); boolean compare1and2 = FileUtils.contentEquals(file1, file2); boolean compare2and3 = FileUtils.contentEquals(file2, file3); boolean compare1and3 = FileUtils.contentEquals(file1, file3); System.out.println("Are test1.txt and test2.txt the same? " + compare1and2); System.out.println("Are test2.txt and test3.txt the same? " + compare2and3); System.out.println("Are test1.txt and test3.txt the same? " + compare1and3); } } 

Tuve un escenario en el que tuve que comparar dos archivos (videos / imágenes / cualquier cosa). Seguí calculando el md5 para los dos archivos y comparándolos. Funcionó bien

 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5EncoderUtility { public String encodeToMd5(String filePath) { MessageDigest md = null; try { md = MessageDigest.getInstance("SHA1"); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } FileInputStream fis = null; try { fis = new FileInputStream(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); } byte[] dataBytes = new byte[1024]; int nread = 0; try { while ((nread = fis.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); } } catch (IOException e) { e.printStackTrace(); } byte[] mdbytes = md.digest(); // convert the byte to hex format StringBuffer sb = new StringBuffer(""); for (int i = 0; i < mdbytes.length; i++) { sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); } System.out.println("Digest(in hex format):: " + sb.toString()); return sb.toString(); } } 

 public class FileCompareUtility { MD5EncoderUtility md5EncoderUtil = new MD5EncoderUtility(); public boolean compare2Files(String actualFilePath, String expectedFilePath) { if ((md5EncoderUtil.encodeToMd5(actualFilePath)).equals(md5EncoderUtil.encodeToMd5(expectedFilePath))) { System.out.println("The files- "+actualFilePath+" and "+expectedFilePath+" are same"); return true; } else { System.out.println("The files- "+actualFilePath+" and "+expectedFilePath+" are NOT same"); return false; } } } 

Y se puede llamar de esta manera:

  String actualFileComparePath = "D:/Videos/test.mp4"; String expectedFileComparePath = "D:/Videos/test2.mp4"; // This will compare any types of files- here video.Eg-Video fileCompareUtil.compare2Files(actualFileComparePath, expectedFileComparePath);