web-dev-qa-db-fra.com

Déterminer si deux fichiers stockent le même contenu

Comment écririez-vous un Java function boolean sameContent(Path file1,Path file2)] qui détermine si les deux chemins indiqués pointent vers des fichiers qui stockent le même contenu? Bien sûr, tout d'abord, je vérifierais si la taille des fichiers sont les mêmes. C’est une condition nécessaire pour stocker le même contenu. Mais j’aimerais écouter vos approches. Si les deux fichiers sont stockés sur le même disque dur (comme dans la plupart de mes cas), ce n’est probablement pas le cas. meilleur moyen de sauter trop de fois entre les deux flux.

59

Exactement quoi FileUtils.contentEquals méthode des communes Apache IO fait et api est ici .

Essayez quelque chose comme:

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

Il effectue les vérifications suivantes avant de faire la comparaison:

  • existence des deux fichiers
  • Les deux fichiers transmis doivent être de type de fichier et non de répertoire.
  • longueur en octets ne devrait pas être la même.
  • Les deux sont des fichiers différents et non un seul et même.
  • Ensuite, comparez le contenu.
77
SMA

Si vous ne souhaitez utiliser aucune bibliothèque externe, lisez simplement les fichiers dans des tableaux d'octets et comparez-les (cela ne fonctionnera pas avant Java-7):

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

en utilisant Arrays.equals .

Si les fichiers sont volumineux, au lieu de lire tous les fichiers dans des tableaux, vous devez utiliser BufferedInputStream et lire les fichiers morceau par morceau comme expliqué ici .

21
Chthonic Project

Si les fichiers sont petits, vous pouvez les lire dans la mémoire et comparer les tableaux d'octets.

Si les fichiers ne sont pas petits, vous pouvez calculer les hachages de leur contenu (par exemple, MD5 ou SHA-1) l'un après l'autre et comparer les hachages (mais cela ne laisse que très peu de risque d'erreur), ou vous pouvez comparer leur contenu, mais pour cela, vous devez toujours lire les flux en alternance.

Voici un exemple:

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
        // (e.g. 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;
}
11
icza

This devrait vous aider avec votre problème:

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);
    }
}
5
peterremec

Depuis Java 12 il existe une méthode Files.mismatch qui retourne -1 s'il n'y a pas d'incompatibilité dans le contenu des fichiers. Ainsi, la fonction ressemblerait à ce qui suit:

private static boolean sameContent(Path file1, Path file2) throws IOException {
    return Files.mismatch(file1, file2) == -1;
}
1
Nolequen
package test;  

      import org.junit.jupiter.api.Test;

      import Java.io.IOException;
      import Java.nio.file.FileSystems;
      import Java.nio.file.Files;
      import Java.nio.file.Path;

import static org.junit.Assert.assertEquals;

public class CSVResultDIfference {

   @Test
   public void csvDifference() throws IOException {
       Path file_F = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestX", "yolo2.csv");
       long size_F = Files.size(file_F);
       Path file_I = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestZ", "yolo2.csv");
       long size_I = Files.size(file_I);
       assertEquals(size_F, size_I);

   }
}

cela a fonctionné pour moi :)

0
yolo