Java文件等于

Java文件等于,java,file,compare,equals,Java,File,Compare,Equals,我不知道你们的情况,但至少我认为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");

我不知道你们的情况,但至少我认为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));
    }
}

以下是两种方法的实现:

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

如果您使用的是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());
它会打印出来

.\hello.txt
hello.txt

因此,它们并不相等,因为使用文件对象的路径属性进行比较

如果只想比较每个文件的内容,可以将内容读入如下字节数组:

byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);
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();
然后比较你想要的

注意,这个方法调用只存在于Java7中。对于旧版本,Guava和Apache有类似的方法,但名称和细节不同

编辑:或者更好的选择(特别是在比较大文件时)可能是简单地逐字节比较,而不是将整个文件加载到内存中,如下所示:

byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);
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();

然后从那里比较。

不是,不是这样。因为equals是比较绝对路径的相等性(在上面的例子中,它类似于:

some-project\.\hello.txt
some-project\hello.txt
所以他们自然是不同的

    public int compare(File f1, File f2) {
      return f1.getPath().compareToIgnoreCase(f2.getPath());
    }
似乎我必须写我自己的equals方法来支持它, 对吧?

可能是的。但首先,您必须知道要比较什么?仅比较路径名?如果是,请按以下方式比较其规范路径:

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

但是,如果您想要比较两个不同文件的内容,那么,您应该编写自己的方法-或者只是从internet上的某个地方复制。

要正确地测试equals,您必须调用getCanonicalFile()


将为等于返回true。请注意,getCanonicalFile可能会抛出IOException,因此我将其添加到方法签名中。

我发现在两个文件上区分的更快方法如下

这只是解决问题的建议

不确定性能(如果每个文件都是10 GB怎么办?)

File File=new文件(“/tmp/File.txt”);
File secondFile=新文件(“/tmp/secondFile.txt”);
//字节差异
byte[]b1=Files.readAllBytes(file.toPath());
byte[]b2=Files.readAllBytes(secondFile.toPath());
布尔等于=数组。等于(b1,b2);
System.out.println(“相同?”+相等);
//列表差异
列表c1=Files.readAllLines(file.toPath());
List c2=Files.readAllLines(secondFile.toPath());
布尔containsAll=c1。containsAll(c2);
System.out.println(“相同?”+containsAll);
}
编辑

但是,unix系统上的diff实用程序会更快、更冗长。
取决于您需要比较的内容。

如果您只想根据路径使用情况检查文件是否相同

java.nio.file.Files#isSameFile

例如


实际上我想做一些类似“fileList.contains(file)”的事情,这个方法调用equals方法。答案让我感到困惑。请参阅jdk中UnixFileSystem.java的源代码:public int compare(file f1,file f2){return f1.getPath().compareTo(f2.getPath());}@我不同意G.Demecki的观点:equals是比较绝对路径的相等+1个不错的帖子-今天我学到了一些东西(我还没有使用Java7,很高兴看到他们添加了一个文件实用程序)如果可以的话,我会先比较文件的大小。比较像that@unbeli请详细说明。我在很多单元测试中使用过类似的代码,其中一个文件包含正确的结果,另一个文件包含程序/算法生成的结果。OP不想这样做(正如他后来详细阐述的那样)但是Brian说了内容,他甚至把它大写。@user949300感谢我的帖子中添加的内容Java 7的Path类也是如此。但是也有类似Path.normalize()或Files.isSameFile()的方法通过显示实际输出,您可以在一段时间内保护这个问题的所有观众。我原以为
equals
compareTo
的结果是矛盾的。事实并非如此,
equals
返回false,而
compareTo
返回-58,这在词典中表示“小于”.@Luciano:请注意,
Files.isSameFile
在这种情况下会尝试打开文件,因为路径不相等,可能会因
NoSuchFileException
而失败。
Assert.assertTrue(Files.isSameFile(
     new File("some-project\.\hello.txt").toPath(),
     new File("some-project\hello.txt").toPath()
));