2012-01-19 1 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クラスでも同じことが起こります。しかし、Path.normalize()やFiles.isSameFile()のようなメソッドがあります – Luciano

+0

実際の出力を表示することで、この質問のすべてのビューアを安全にすることができます。私は 'equals'と' compareTo'が矛盾する結果を持っていることを期待していました。これはそうではなく、 'equals'はfalseを返し、' compareTo'は-58を返します。これは辞書編集的に "less than"を意味します。 @Luciano:パスが等しくなく、 'NoSuchFileException'で失敗する可能性があるので、' Files.isSameFile'はこの場合ファイルを開こうとします。 – bluenote10

答えて

30

そうではありません。 はそれ以上のあなたのケースでは、絶対パスの平等を(比較される等しいためのようなものです:。

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

私は自分のequalsメソッドを記述する必要がありますようだから彼らは当然異なっている

に思えますはいおそらく、 右?

それをサポートしています。しかし、すべての最初のために、あなたが比較したいものを知っている必要がありますか?はいだけならば、その中に正規のパスを比較する?パス名この方法:

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

しかし、あなたは2つの異なるファイルの内容を比較したい場合は、その後、はい、独自のメソッドを記述する必要があります - または単にちょうど、インターネット上のどこかからコピーします。

よろしく

+1

私は実際に "fileList"のようなことをしたいと思っています。contains(file) "であり、このメソッドは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

Windowsを使用している場合は、比較の方法は、以下のようなものですので、それは非常にあるクラスWin32FileSystem

を見ますあなたのファイルオブジェクトが異なっているのが普通です。

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

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

同様にあなたのコードにこれらの行を追加し、それが比較はFileオブジェクトのパスproeprtyを使用して作られているとしてそれゆえ、彼らは同じではありません

.\hello.txt 
hello.txt 

を印刷します

4

各ファイルのCONTENTSのみを比較したい場合は、内容をバイトar

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

を比較そこから。

+0

+1すてきな投稿 - 私は今日何かを学んだ(私はまだJava 7を使用していない、彼らはファイルユーティリティを追加して嬉しい) – 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

私は2つのファイルを比較するためのより速い方法を以下に示します。

これは、それを回避するための単なる命題です。

パフォーマンスわからない(どのファイルが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システム上の差分ユーティリティは、はるかに高速かつ冗長になります。 あなたが比較する必要があるものによって異なります。