Java 文件等于

发布于 2024-12-28 01:37:25 字数 545 浏览 4 评论 0原文

我不知道你们怎么想,但至少我预计下面的代码中 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));
    }
}

I don't know about you guys but at least I expected that f1 would be equal to f2 in the below code but apparently that's not the case! What's your thoughts about this? It seems like I have to write my own equals method to support it, right?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

牵你的手,一向走下去 2025-01-04 01:37:25

不,事实并非如此。因为 equals 正在比较绝对路径的相等性(在上面的例子中,它类似于:

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

所以它们自然是不同的。

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

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

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

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

Not, it's not the case. Because equals is comparing equality of absolute paths (in your case above it is something like:

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

So they are naturally different.

It seems like I have to write my own equals method to support it,
right?

Probably yes. But first of all, you have to know what you want to compare? Only pathnames? If yes, compare its canonical path in this way:

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

But if you want compare content of two different files, then yes, you should write your own method - or simply just copy from somewhere on the internet.

玻璃人 2025-01-04 01:37:25

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

To properly test equals, you must call getCanonicalFile(). e.g.

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

Will return true for equals. Note that getCanonicalFile may throw an IOException so I added that to the method signature.

可遇━不可求 2025-01-04 01:37:25

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

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

然后从那里进行比较。

If you only want to compare the CONTENTS of each file, you could read the contents into a byte array like this:

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

And then compare exactly what you want from there.

Note that this method call only exists in Java 7. For older versions, Guava and Apache have methods to do similar but with different names and details.

Edit: OR a better option (especially if you're comparing large files) might be to simply compare byte by byte rather than loading the entire file into memory, like this:

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

And then compare from there.

仙气飘飘 2025-01-04 01:37:25

我发现比较两个文件的更快方法如下。

这只是解决这个问题的建议。

不确定性能(如果每个文件都是 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<String> c1 = Files.readAllLines(file.toPath());
    List<String> c2 = Files.readAllLines(secondFile.toPath());

    boolean containsAll = c1.containsAll(c2);
    System.out.println("the same? " + containsAll);                
}

编辑

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

The quicker way I found to diff on two files is below.

That's just proposition to work it around.

Not sure about the performance (what if files are 10 GB each?)

    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

But still, diff utility on unix system would be much quicker and verbose.
Depends what you need to compare.

素染倾城色 2025-01-04 01:37:25

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

java.nio.file.Files#isSameFile

例如

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

If you just want to check if the files are the same based on their path use

java.nio.file.Files#isSameFile

E.g.

Assert.assertTrue(Files.isSameFile(
     new File("some-project\.\hello.txt").toPath(),
     new File("some-project\hello.txt").toPath()
));
甜是你 2025-01-04 01:37:25

下面是这两种方法的实现:

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

Here is the implementation of both methods:

/**
 * 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);
}
诗酒趁年少 2025-01-04 01:37:25

如果您使用的是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 对象的路径属性进行比较

If you are using windows see class Win32FileSystem

The comparison method is like below, so it is very normal that your file objects are different.

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

Add those lines to your code as well

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

and it will print

.\hello.txt
hello.txt

Hence they are not equal as the comparison is made using path proeprty of File object

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文