java.io.File。<init>(File,String)取决于JDK版本

时间:2018-09-03 13:54:03

标签: java file java-8 java-io java-9

java.io.File。(文件,字符串)似乎与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
}

请问该案件是否存在任何已知问题或解决方案

3 个答案:

答案 0 :(得分: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()来不解析文件系统的路径。

答案 1 :(得分:4)

@david答案的补充,

它是一个 bug#8153250 ,它是地址,并且提供了固定版本JDK 9 b153

答案 2 :(得分:1)

@davidxxx在初始File实例上指出getAbsolutePathpublic 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()); } 对于Java8和Java9是相同的。但是,如果您决定使用此初始文件来创建新文件,您可能会对这些差异感到惊讶-至少我是这样。

file

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

输出Java 8:

  

C:
  C:\ ws \ PLAYGROUND \ test
  ----
  C:\ Windows
  C:\ Windows

输出Java 9:

  

C:
  C:\ ws \ PLAYGROUND \ test
  ----
  C:Windows
  C:\ ws \ PLAYGROUND \ test \ Windows