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

不是,事实并非如此。 因为equals是比较绝对路径的相等性(在你的情况下,它类似于:

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

所以他们自然不同。

看来我必须编写自己的equals方法来支持它,对吗?

可能是。 但首先,你必须知道你想要比较什么? 只有路径名? 如果是,请以这种方式比较其规范路径:

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

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

要正确测试equals,必须调用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,因此我将其添加到方法签名中。

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

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

然后从那里进行比较。

我发现两个文件差异的更快的方法如下。

这只是为了解决这个问题的主张。

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

  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 c1 = Files.readAllLines(file.toPath()); List c2 = Files.readAllLines(secondFile.toPath()); boolean containsAll = c1.containsAll(c2); System.out.println("the same? " + containsAll); } 

编辑

但是,unix系统上的diff实用程序会更加快速和冗长。 取决于你需要比较的东西。

以下是两种方法的实现:

 /** * Tests this abstract pathname for equality with the given object. * Returns true if and only if the argument is not * null 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 true if and only if the objects are the same; * false 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); } 

如果您使用的是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 

因此,它们不相等,因为使用File对象的路径proeprty进行比较

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

java.nio.file.Files#isSameFile

例如

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