Java Paths.get() Linux 上的奇怪行为

Java Paths.get() strange behavior on Linux

我目前正在编写一些代码,其中我经常使用文件。我使用 Java 7 nio classes 路径和路径实现了所有文件路径处理(连接、规范化等)。在 Windows 上,一切都按预期工作,但是在 Linux 上,路径 class 行为似乎被破坏了。

例如下面的代码:

    System.out.println(File.separator);
    System.out.println(FileSystems.getDefault());
    Path path = Paths.get("../dir1/", "\dir2\file1").toAbsolutePath().normalize();
    System.out.println(path);
    if(path.toFile().exists()) {
        System.out.println(path + " exists");
    }

on Windows 打印以下输出:

\
sun.nio.fs.WindowsFileSystem
D:\projects\dir1\dir2\file1
true

但 Linux Ubuntu 14.04 上的代码相同 Java 1.7.0_79(64 位)和 Java 1.8.0_60(64 位)使路径未规范化:

/
sun.nio.fs.LinuxFileSystem
/home/semi/dir1/\dir2\file1

此外,即使文件位于路径 /home/semi/dir1/dir2/file1 中,它也被 path.toFile().exists() 报告为不存在。

我仔细查看了 LinuxFileSystem.java and WindowsFileSystem.java,似乎在 windows 上检查了 /\ 字符的路径(在 WindowsPathParser.isSlash(char c)方法)。 Linux 实现不应该做同样的事情吗?

这是 sun.nio.fs.LinuxFileSystem 实现中的错误还是我做错了什么?

您还知道任何其他方法来确保 Linux 路径被正确解析和规范化(无需手动进行所有解析)。

在 Windows 中,/ 不是文件名中的有效字符,因此任何代码都可以假定它是错误键入的路径分隔符。

在 Linux 中,文件名中几乎可以接受任何字节。在您的 Paths.get() 中,您有效地加入了一条名为 dir1 的路径(1 级深)和一条名为 \dir2\file1 的路径(也是 1 级深)。

Java on Windows 是根据 Microsoft C++ 标准库编译的,它允许反斜杠或正斜杠作为有效的路径分隔符。所以反斜杠只有在 Windows 上 运行 时才是有效的路径分隔符,而正斜杠在任何地方都有效。

唯一一次需要反斜杠,即使在 Windows 上也是如此,这是在创建将传递给 CMD.EXE、PowerShell 以及可能的其他 terminals/shells 的命令行时。还有一些开源库要求在文件路径中使用反斜杠(当 运行 on Windows 时),但 java 本身允许在文件路径中使用正斜杠或反斜杠。

恕我直言,在解析输入时使用 File.separator 通常会导致可避免的错误,而在生成供软件或人眼使用的输出时它具有有效的作用。