web-dev-qa-db-fra.com

Fichier Java est égal à

Je ne sais pas pour vous les gars, mais au moins je m'attendais à ce que F1 soit égal à f2 dans le code ci-dessous, mais apparemment ce n'est pas le cas! Que pensez-vous de cela? Il semble que je doive écrire ma propre méthode d'égalité pour la prendre en charge, non?

import Java.io.*;

public class FileEquals
{
    public static void main(String[] args)
    {
        File f1 = new File("./hello.txt");
        File f2 = new File("hello.txt");
        System.out.println("f1: " + f1.getName());
        System.out.println("f2: " + f2.getName());
        System.out.println("f1.equals(f2) returns " + f1.equals(f2));
        System.out.println("f1.compareTo(f2) returns " + f1.compareTo(f2));
    }
}
20
aandeers

Non, ce n'est pas le cas. Parce que equals compare l’égalité des chemins absolus (dans votre cas ci-dessus, cela ressemble à quelque chose comme:

some-project\.\hello.txt
some-project\hello.txt

Donc, ils sont naturellement différents.

Il semble que je doive écrire ma propre méthode d'égalité pour la prendre en charge, N'est-ce pas?

Probablement oui. Mais avant tout, vous devez savoir ce que vous voulez comparer? Seulement les noms de chemin? Si oui, comparez son chemin canonique de la manière suivante:

f1.getCanonicalPath().equals(f2.getCanonicalPath())

Mais si vous voulez comparer le contenu de deux fichiers différents, alors oui , vous devriez écrire votre propre méthode - ou simplement copier depuis quelque part sur Internet.

32
G. Demecki

Pour tester correctement l'égalité, vous devez appeler getCanonicalFile (). par exemple.

public static void main(String[] args) throws IOException
   {
       File f1 = new File("./hello.txt").getCanonicalFile();
       File f2 = new File("hello.txt").getCanonicalFile();
       System.out.println("f1: " + f1.getAbsolutePath());
       System.out.println("f2: " + f2.getAbsolutePath());
       System.out.println("f1.equals(f2) returns " + f1.equals(f2));
       System.out.println("f1.compareTo(f2) returns " + f1.compareTo(f2));
   }

Reviendra vrai pour égaux. Notez que getCanonicalFile peut générer une exception IOException et que je l'ai ajoutée à la signature de la méthode.

8
user949300

Si vous souhaitez uniquement comparer le contenu de chaque fichier, vous pouvez lire le contenu dans un tableau d'octets comme ceci:

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

Et puis comparez exactement ce que vous voulez à partir de là.

Notez que cet appel de méthode n'existe que dans Java 7. Pour les versions plus anciennes, Guava et Apache disposent de méthodes similaires, mais avec des noms et des détails différents.

Éditer: OR une meilleure option (surtout si vous comparez des fichiers volumineux) peut consister simplement à comparer octet par octet au lieu de charger tout le fichier en mémoire, comme ceci:

FileInputStream f1 = new FileInputStream(file1);
DataInputStream d1 = new DataInputStream(f1);
FileInputStream f2 = new FileInputStream(file2);
DataInputStream d2 = new DataInputStream(f2);

byte b1 = d1.readByte();
byte b2 = d2.readByte();

Et puis comparer à partir de là.

4
Brian Snow

Le moyen le plus rapide que j'ai trouvé de diff sur deux fichiers est ci-dessous. 

C'est juste proposition de contourner le problème.

Pas sûr de la performance (que se passe-t-il si les fichiers font 10 Go chacun?)

    File file = new File("/tmp/file.txt");
    File secondFile = new File("/tmp/secondFile.txt");

    // Bytes diff
    byte[] b1 = Files.readAllBytes(file.toPath());
    byte[] b2 = Files.readAllBytes(secondFile.toPath());

    boolean equals = Arrays.equals(b1, b2);

    System.out.println("the same? " + equals);

    // List Diff
    List<String> c1 = Files.readAllLines(file.toPath());
    List<String> c2 = Files.readAllLines(secondFile.toPath());

    boolean containsAll = c1.containsAll(c2);
    System.out.println("the same? " + containsAll);                
}

MODIFIER

Mais malgré tout, l’utilité diff sur un système unix serait beaucoup plus rapide et détaillée.

2
DevDio

Voici l'implémentation des deux méthodes:

/**
 * Tests this abstract pathname for equality with the given object.
 * Returns <code>true</code> if and only if the argument is not
 * <code>null</code> and is an abstract pathname that denotes the same file
 * or directory as this abstract pathname.  Whether or not two abstract
 * pathnames are equal depends upon the underlying system.  On UNIX
 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
 * systems it is not.
 *
 * @param   obj   The object to be compared with this abstract pathname
 *
 * @return  <code>true</code> if and only if the objects are the same;
 *          <code>false</code> otherwise
 */
public boolean equals(Object obj) {
    if ((obj != null) && (obj instanceof File)) {
        return compareTo((File)obj) == 0;
    }
    return false;
}
/**
 * Compares two abstract pathnames lexicographically.  The ordering
 * defined by this method depends upon the underlying system.  On UNIX
 * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
 * systems it is not.
 *
 * @param   pathname  The abstract pathname to be compared to this abstract
 *                    pathname
 *
 * @return  Zero if the argument is equal to this abstract pathname, a
 *          value less than zero if this abstract pathname is
 *          lexicographically less than the argument, or a value greater
 *          than zero if this abstract pathname is lexicographically
 *          greater than the argument
 *
 * @since   1.2
 */
public int compareTo(File pathname) {
    return fs.compare(this, pathname);
}
1
Eng.Fouad

Si vous voulez juste vérifier si les fichiers sont les mêmes en fonction de leur chemin, utilisez

Java.nio.file.Files#isSameFile

Par exemple.

Assert.assertTrue(Files.isSameFile(
     new File("some-project\.\hello.txt").toPath(),
     new File("some-project\hello.txt").toPath()
));
0
EliuX

Si vous utilisez Windows, consultez la classe Win32FileSystem

La méthode de comparaison est comme ci-dessous, il est donc très normal que vos objets de fichier soient différents.

    public int compare(File f1, File f2) {
      return f1.getPath().compareToIgnoreCase(f2.getPath());
    }

Ajoutez également ces lignes à votre code

        System.out.println(f1.getPath());
        System.out.println(f2.getPath());

et ça va imprimer

.\hello.txt
hello.txt

Par conséquent, ils ne sont pas égaux car la comparaison est faite en utilisant le chemin path de l’objet File.

0
fmucar