java.io.File中。 (文件,字符串)依赖于JDK版本[重复]

问题描述 投票:8回答:3

这个问题在这里已有答案:

它看起来像java.io.File。(File,String)依赖于JDK版本。代码示例在Windows 10上运行。

代码示例:

public static void main(String... args) {
    String path = "C:\\Workspace\\project";
    File file = null;
    for (String part : path.split("\\\\")) {
        file = new File(file, part);
    }
    System.out.println(file);
    // prints "C:Workspace\project" for JDK 9+
    // prints "C:\Workspace\project" for JDK 8
}

您能否解决该案件的任何已知问题或解决方案

java file java-8 java-io java-9
3个回答
7
投票

在Java 9中,WinNTFileSystem类(Windows的FileSystem实现)发生了变化。 它可能解决了类认为绝对路径是什么的问题。我没有找到一个确切指定这个的错误但有些接近。

File.isAbsolute()说:

在Microsoft Windows系统上,如果路径名的前缀是驱动器说明符后跟“\”,或者前缀为“\\”,则路径名是绝对路径。

所以根据规范,对于以下内容:

File x = new File("C:", "Workspace"); 
System.out.println(x.isAbsolute()); // not absolute according to the spec

File xx = new File("C:\\", "Workspace");
System.out.println(xx.isAbsolute());

File xxx = new File("\\\\Workspace");
System.out.println(xxx.isAbsolute());

我们期待 :

假真的是真的

但我们得到:

的确如此

从Java 9开始,它产生了预期的结果。

问题是在Java 9之前没有\的路径被认为是绝对路径:

File x = new File("C:", "Workspace");
System.out.println(x.isAbsolute()); // true

虽然这不应该是这种情况。

具体而言,主要变化涉及resolve(String parent, String child)类的WinNTFileSystem方法。 之前,resolve()解决了抽象路径,在父节点和子节点之间添加了一个斜杠,用于任何不以斜杠开头的子路径。 从Java 9开始,如果父驱动器是父驱动器,则resolve()不会在父驱动器和子驱动器之间添加斜杠。

这是change

boolean isDirectoryRelative =
    pn == 2 && isLetter(parent.charAt(0)) && parent.charAt(1) == ':';

if (child.charAt(childStart) == slash || isDirectoryRelative) {
    theChars = new char[strlen];             ^-------- this one was added from Java 9
    parent.getChars(0, parentEnd, theChars, 0);
    child.getChars(childStart, cn, theChars, parentEnd);
} else {
    theChars = new char[strlen + 1];
    parent.getChars(0, parentEnd, theChars, 0);
    theChars[parentEnd] = slash;
    child.getChars(childStart, cn, theChars, parentEnd + 1);
}

后果

关于你的问题:

您能否解决该案件的任何已知问题或解决方案

两个JDK版本之间的区别很重要。它既涉及抽象路径名的规范化路径名(File.getPath())的值,也涉及绝对路径File.getAbsolutePath()的值,因为现在new File("C:", "Workspace")产生相对路径。

如果您的应用程序依赖于File.getPath()对其进行一些解析,则可能会产生明显的行为并产生一些问题。 要在JDK版本之间拥有可移植代码,解析路径上的任何解析都应该视为Windows驱动器之后的\可选。 这样,C:\C:将以同样的方式处理。

如果你的应用程序依赖于File.getAbsolutePath(),它也可能会有一些来自Java 9的惊喜,因为现在相对的路径将被解析为文件系统(之前作为一个绝对路径,它刚才返回)。 所以相反,您应该使用File.getPath()来解决文件系统的路径。


4
投票

除了@david回答,

这是一个bug#8153250,这是地址和固定版本可用JDK 9 b153


1
投票

正如@davidxxx所指出的,初始File实例上的getAbsoluteFilegetAbsolutePath与Java8和Java9相同。但是,如果您决定使用此初始文件来创建新文件,您可能会对这些差异感到惊讶 - 至少我是这样。

public static void main(String[] args) throws Exception {

    File file = new File((File)null, "C:");
    System.out.println(file);
    System.out.println(file.getAbsoluteFile());

    System.out.println("----");

    file = new File(file, "Windows");
    System.out.println(file);
    System.out.println(file.getAbsoluteFile());
}

如果使用Java 8和9执行上述程序,file将在第二次分配后指向完全不同的文件夹。由于Java8和9的初始文件是相同的,我实际上认为这是Java 8中的错误(可能之前)。

输出Java 8:

C: C:\ WS \组合滑梯\测试 ---- C:\ WINDOWS C:\ WINDOWS

输出Java 9:

C: C:\ WS \组合滑梯\测试 ---- C:的Windows C:\ WS \操场\测试\ Windows下

© www.soinside.com 2019 - 2024. All rights reserved.