2012-01-19 2 views
19

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

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

То же самое происходит с классом пути Java 7. Но существуют такие методы, как Path.normalize() или Files.isSameFile() – Luciano

+0

Вы можете безопасно просмотреть всех зрителей этого вопроса, показывая фактический вывод. Я ожидал, что 'equals' и' compareTo' противоречат результатам. Это не так, 'equals' возвращает false и' compareTo' возвращает -58, что означает лексикографически «меньше». @Luciano: Обратите внимание, что 'Files.isSameFile' в этом случае попытается открыть файлы, так как пути не равны и могут завершиться с' NoSuchFileException'. – bluenote10

ответ

30

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

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

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

Похоже, я должен написать мой собственный равен метод чтобы поддержать его, правильно?

Вероятно, да. Но в первую очередь, вы должны знать, что вы хотите сравнить? только имена маршрута? Если да, то сравнить его канонический путь в таким образом:

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

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

С уважением

+1

Я действительно хочу сделать что-то вроде «fileList.содержит (файл) ", и этот метод вызывает метод equals. – aandeers

1

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

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

Если вы используете окна см класс 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 

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

4

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

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

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

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

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

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

А потом сравнить оттуда.

+0

+1 Хорошее сообщение - сегодня я чему-то научился (я еще не использовал Java 7, рад видеть, что они добавили утилиту Files) – user949300

+1

Сначала я бы сравнил размер файлов, если он доступен. – Luciano

+5

это невероятно плохая идея, чтобы сравнить файлы вроде этого – unbeli

7

Чтобы правильно проверить, равен, вы должны вызвать 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, поэтому я добавил его к сигнатуре метода.

2

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

Это просто предложение поработать вокруг.

Не уверен, что о производительности (что, если файлы 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);     
} 

EDIT

Но все-таки, дифф утилита в системе UNIX будет гораздо быстрее и многословным. Зависит от того, что вам нужно сравнить.

Смежные вопросы