Java,Linux:如何检测两个java.io.Files是否引用相同的物理文件

mst*_*rap 9 java unix file equals

我正在寻找一种有效的方法来检测两个是否java.io.File引用相同的物理文件.根据文档,File.equals() 应该做的工作:

测试此抽象路径名与给定对象的相等性.当且仅当参数不为null并且是表示与此抽象路径名相同的文件或目录的抽象路径名时,返回true.

但是,给定一个安装在/ media/truecrypt1的FAT32分区(实际上是TrueCrypt容器):

new File("/media/truecrypt1/File").equals(new File("/media/truecrypt1/file")) == false
Run Code Online (Sandbox Code Playgroud)

你会说这符合规范吗?在这种情况下,如何解决这个问题?

更新:感谢评论者,对于Java 7,我发现java.io.Files.isSameFile()哪些对我有用.

Ste*_*n C 14

@Joachim的评论中的答案通常是正确的.确定两个File对象是否引用相同OS文件的方法是使用getCanonicalFile()或getCanonicalPath().javadoc说:

"规范路径名是绝对的和唯一的.[...]每个表示现有文件或目录的路径名都具有唯一的规范形式."

所以以下应该有效:

File f1 = new File("/media/truecrypt1/File");  // different capitalization ...
File f2 = new File("/media/truecrypt1/file");  // ... but same OS file (on Windows)
if (f1.getCanonicalPath().equals(f2.getCanonicalPath())) {
    System.out.println("Files are equal ... no kittens need to die.");
}
Run Code Online (Sandbox Code Playgroud)

但是,您似乎正在查看安装在UNIX/Linux上的FAT32文件系统.AFAIK,Java并不知道这种情况正在发生,并且只是对文件名应用通用的UNIX/Linux规则......在这种情况下给出了错误的答案.

如果这是真正发生的事情,我认为纯Java 6中没有可靠的解决方案.但是,

  • 你可以做一些毛茸茸的JNI东西; 例如,获取文件描述符编号,然后在本机代码中,使用fstat(2)系统调用来获取两个文件的设备和inode编号并进行比较.

  • 如果首先调用路径来解析符号链接,Java 7 java.nio.file.Path.equals(Object)看起来可能会给出正确的答案resolve().(从javadoc有点不清楚Linux上每个挂载的文件系统是否都对应一个不同的FileSystem对象.)

  • 在Java 7的教程有本节上看到如果两个Path对象是同一个文件......这建议使用java.nio.file.Files.isSameFile(Path, Path)


你会说这符合规范吗?

不,是的.

  • 从某种意义上说,该getCanonicalPath()方法没有为每个现有的OS文件返回相同的值...这是您对读取javadoc的期望.

  • 是技术意义上的,Java代码库(不是javadoc)是最终的规范......无论是在理论上还是在实践中.