Подтвердить что ты не робот

Файл Java равен

Я не знаю о вас, ребята, но, по крайней мере, я ожидал, что f1 будет равен f2 в приведенном ниже коде, но, по-видимому, это не так! Что вы думаете об этом? Кажется, я должен написать свой собственный метод equals для его поддержки, верно?

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));
    }
}
4b9b3361

Ответ 1

Не, это не так. Поскольку equals сравнивает равенство абсолютных путей (в вашем случае выше это что-то вроде:

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

Таким образом, они, естественно, различны.

Кажется, я должен написать свой собственный метод equals для его поддержки, не так ли?

Вероятно, да. Но прежде всего, вы должны знать, что вы хотите сравнить? Только пути? Если да, сравните его канонический путь следующим образом:
f1.getCanonicalPath().equals(f2.getCanonicalPath())

Но если вы хотите сравнить содержимое двух разных файлов, то да, вы должны написать свой собственный метод - или просто просто скопировать откуда-то в Интернете.

Привет

Ответ 2

Чтобы правильно проверить равные, вы должны вызвать getCanonicalFile(). например.

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

Вернет true для равных. Обратите внимание, что getCanonicalFile может генерировать исключение IOException, поэтому я добавил его к сигнатуре метода.

Ответ 3

Если вы хотите сравнить СОДЕРЖАНИЕ каждого файла, вы можете прочитать содержимое в байтовый массив следующим образом:

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

И затем сравните то, что вы хотите оттуда.

Обратите внимание, что этот вызов метода существует только в Java 7. Для более старых версий у Guava и Apache есть методы для работы аналогичными, но с разными именами и деталями.

Изменить: ИЛИ лучший вариант (особенно если вы сравниваете большие файлы) может состоять в том, чтобы просто сравнивать байты по байтам, а не загружать весь файл в память, например:

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();

И затем сравните оттуда.

Ответ 4

Более быстрый способ обнаружения двух файлов приведен ниже.

Это просто предложение для его работы.

Не уверен в производительности (что, если файлы по 10 ГБ каждый?)

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

ИЗМЕНИТЬ

Но все-таки утилита diff для unix-системы была бы намного быстрее и подробней. Зависит от того, что вам нужно сравнить.

Ответ 5

Вот реализация обоих методов:

/**
 * 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);
}

Ответ 6

Если вы используете окна, см. класс Win32FileSystem

Метод сравнения подобен ниже, поэтому очень нормально, что ваши объекты файлов отличаются.

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

Добавьте эти строки в свой код, а также

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

и он напечатает

.\hello.txt
hello.txt

Следовательно, они не равны, поскольку сравнение производится с использованием метода proteprty объекта File

Ответ 7

Если вы просто хотите проверить, одинаковы ли файлы на основе их использования пути

java.nio.file.Files#isSameFile

Например

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