在处理某些 File 对象时,我遇到了我认为不寻常的行为。
import java.io.File;
public class MyClass
{
public static void main(String[] args)
{
File file = new File("C:\\x..");
System.out.println(file.isDirectory());
System.out.println(file.listFiles());
}
}
假设某个目录 C:\x
存在,file.isDirectory()
将返回 true 并在路径末尾添加两个点。这复制了命令行中的行为,其中 cd x..
会将目录更改为 x
。
但是,当调用 file.listFiles()
时,该方法返回 null,这只有在文件不是目录时才会发生。这似乎与 listFiles()
的定义不一致。
为什么会这样?为什么在路径末尾有两个点会转到同一个目录,就好像没有点一样?
这个问题似乎是 Windows 独有的。 Linux 正确 (?) 为 isDirectory()
返回 false。
最佳答案
Windows 修剪路径和文件名中的尾随点。我无法为此找到具体的引用,它只是那些一直如此的神秘事物之一。
它会修剪完整路径名的尾随点,而不是单个组件。
因此,虽然“C:\x....”与“C:\x”相同,但“C:\x....\filename”与“C:\x\filename",因为后者没有尾随点。
您必须在 Windows 上查看 JDK 的 native FileSystem
源代码才能准确了解它是如何获取文件列表的,但我怀疑它正在对例如文件进行某种搜索。 “C:\x..\*.*”使用 Windows 的 FindFirstFile
API 调用或其他方式,其中点不再尾随。也就是说,假设“C:\x”是一个目录,而路径“C:\x..”是一个目录,“C:\x..\*.*”什么都不匹配,而“C:\x..\subdirectory”不映射到“C:\x\subdirectory”。
你应该避免使用这样的路径。我不确定您最初是如何获得该路径字符串的。
您可以使用 File.getCanonicalPath()
或 File.getCanonicalFile()
将其转换回更有用的路径名。
顺便说一下,如果你想在 Windows 上玩得开心,请在命令提示符中键入以下内容(假设“c:\windows\temp”存在,否则替换为其他路径):
echo > \\?\c:\windows\temp\x.
Windows 中的 \\?\
前缀禁用文件名处理和扩展。现在删除生成的文件。也可以在资源管理器中尝试。
剧透:
您必须从控制台使用通配符将其删除,例如
del x?
关于Java路径末尾的两个点有意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19830016/