Java NIO - Files.isSameFile与Path.equals的区别

13
我不理解java.nio.file.Files.isSameFile方法与java.nio.file.Path.equals方法之间的区别。有人能告诉我它们之间的不同吗?请注意,要保留HTML标记


java.nio.file.Path.isSameFile 不存在。您是否指的是 java.nio.file.Files.isSameFile - Andy Turner
是的,你说得对。哦,那么这个问题就无效了。请求删除此问题。 - user4710520
你可以直接编辑并修正错误。 - fge
我提出这个问题的原因是,我觉得isSameFile和equals在同一类中实现了相似的行为。现在我知道它们来自不同的类,我的原始疑问已经不存在了。 - user4710520
5个回答

27

他们非常不同。

例如:

final Path p1 = Paths.get("/usr/src");
final Path p2 = Paths.get("/usr/../usr/src");

p1.equals(p2); // FALSE
Files.isSameFile(p1, p2); // true

final Path p1 = fs1.getPath("/usr/src");
final Path p2 = fs2.getPath("/usr/src");

p1.equals(p2); // FALSE

如果且仅当以下条件都满足时,Path与另一个Path相等:

  • 它们拥有相同的FileSystem
  • 它们有相同的根元素;
  • 它们拥有相同的名称元素。

这与Files.isSameFile()非常不同,后者访问文件系统并尝试查看两个Path是否指向同一文件系统资源。


好的。所以 equals 只是对其字符串表示进行相等检查,对吗? - user4710520
不,再次阅读答案。 - fge
也许楼主不知道一个文件可以有多个标识它的路径?这些差异从琐碎的(大小写、'..'等元素)到大部分文件系统中的一个文件可以有多个链接指向它的情况。 - Arfur Narf

3
  • 如果equal() == true,则isSameFile() == true
  • 如果isSameFile() == true,则equal()并不总是true

isSameFile()方法首先检查Path对象是否在equal()方面相等,如果是,则自动返回true而不检查任何一个文件是否存在。

如果Path对象的equals()比较返回false,则在文件系统中找到每个路径引用的文件,并确定它们是否相同。如果任何一个文件不存在,则抛出checked IOException异常。


只是补充一下,根据Javadoc,File.isSameFile()可能会抛出异常,而Path.equals()则不会。但是它也提到,在某些情况下,Path.equals()将调用Files.isSameFile()。https://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#equals(java.lang.Object)和https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#isSameFile(java.nio.file.Path,%20java.nio.file.Path) - ptha

1

isSameFile 是来自 java.nio.file.Files 的方法,而 Path.equals 是来自 java.nio.file.Path 的方法。

isSameFile --> 用于测试两个路径是否定位到同一个文件。 即检查两个 Path 对象是否指向同一文件。 equals --> 用于将此路径与给定对象进行比较以测试其相等性。


你说得对,这使得我的问题无效了。我已经请求删除这个问题。不过还是谢谢你的回答。 - user4710520

0

java.nio.file.Files.isSameFile() 检查两个文件路径是否引用同一个文件,即都是硬链接(这对于所有操作系统和文件系统都是可移植的)。此方法也遍历符号链接,然后可以将两个符号链接与指向 Unix 文件系统/Windows NTFS 上相同 inode 的文件名进行比较。

您可以定位(不可编辑)文件重复项(具有相同大小和内容),确定它们是否为软/硬链接,然后如果不是,则可以保存路径名并删除第一个文件,然后创建到第二个文件的链接。您可以节省 50% 的磁盘空间。


0
从我的角度来看,Java API 在这里缺少一些东西...... 应该有一种方法可以知道两个路径是否指向文件系统中的同一个文件夹/文件。而且这应该在没有访问文件系统的情况下执行(假设其中一个路径不存在,使用 java.nio.file.Files.isSameFile() 将会收到 java.nio.file.NoSuchFileException)。另一方面,
Paths.get("/usr/src").equals(Paths.get("/usr/../usr/src"))

将返回一个错误的结果...

针对这种情况的简单解决方案可能是以下内容:

final Path p1 = Paths.get("/usr/src");
final Path p2 = Paths.get("/usr/../usr/src");
final boolean areEqual = p1.normalize().toAbsolutePath().toString().equalsIgnoreCase(p2.normalize().toAbsolutePath().toString());

你对此有何看法?


在文件系统中应该有一种方法来判断两个路径是否指向同一个文件夹/文件。一个系统甚至不能像 "toAbsolutePath()" 这样做,没有访问文件系统的情况下无法检查文件是否存在或不存在,也无法在不访问文件系统的情况下跟随软链接;它也无法检查两个截然不同的路径是否实际上是同一个文件的硬链接而不访问文件系统。 - Andrew Henle
感谢Andrew的评论,你说得对,我不知道toAbsolutePath()也可以访问文件系统。不过,似乎即使路径不存在,它也不会抛出任何异常。我的意思是,我将Path视为系统路径的“逻辑”形式。从这个角度来看,即使是equals()方法也应该以“逻辑”方式而非物理方式工作。当然,链接必须访问文件系统才能进行调查。再次感谢! - Massimo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接