Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.io.File.<init>(File,String) JDK version dependent [duplicate]

It's looks like java.io.File.(File, String) is JDK version dependent. Code example was run on Windows 10.

Code example:

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
}

Could you please address is there any known issue or solution for the case

like image 947
Ivan Kalinin Avatar asked Sep 03 '18 13:09

Ivan Kalinin


People also ask

What is Io file class in Java?

Java.io.File Class in Java. The File class is Java’s representation of a file or directory path name. Because file and directory names have different formats on different platforms, a simple string is not adequate to name them.

What is the file class in Java?

The File class is Java’s representation of a file or directory path name. Because file and directory names have different formats on different platforms, a simple string is not adequate to name them.

What is Nio file in Java?

The java.nio.file package defines interfaces and classes for the Java virtual machine to access files, file attributes, and file systems. This API may be used to overcome many of the limitations of the java.io.File class.

How to create a file object in Java?

A File object is created by passing in a String that represents the name of a file, or a String or another File object. For example, Attention reader! Don’t stop learning now.


2 Answers

In Java 9, the WinNTFileSystem class (FileSystem implementation for windows) changed.
It probably solves a issue which the way the class considers what a absolute path is. I didn't find a bug that exactly specifies this one but some are close to.

File.isAbsolute() states :

On Microsoft Windows systems, a pathname is absolute if its prefix is a drive specifier followed by "\", or if its prefix is "\\".

So according to the specification, for the following:

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());

we expect :

false true true

But we get :

true true true

From Java 9 it produces the expected result.

The problem is that before Java 9 a path without \ is all the same considered as an absolute path :

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

While that this should not be the case.

Concretely, the main changes concern the resolve(String parent, String child) method of the WinNTFileSystem class.
Before, resolve() resolved the abstract path by adding a slash between the parent and the child for any child path that doesn't start with a slash.
From Java 9, resolve() doesn't add a slash any longer between the parent and the child if the parent is a drive.

Here is the 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);
}

Consequences

About your question :

Could you please address is there any known issue or solution for the case

The difference between the two JDK versions matters. It concerns both the value of the abstract pathname's normalized pathname (File.getPath()) and the value of the absolute path File.getAbsolutePath() as now new File("C:", "Workspace") produces a relative path.

If your application relies on File.getPath() to do some parsing on that, it could have a distinct behavior and create some issues.
To have a portable code between the JDK versions, any parsing on the resolved path should consider as optional the \ just after the Windows drive.
In this way C:\ and C: would be handled in the same way.

If your application relies on File.getAbsolutePath(), it could also have some surprises from Java 9 as now the path that is relative will be resolved against the filesystem (before as an absolute path this just returned itself).
So instead, you should so probably use File.getPath() to not resolve the path against the file system.

like image 66
davidxxx Avatar answered Oct 13 '22 07:10

davidxxx


Addition to @david answer,

It was a bug#8153250, which was address and fixed version is available JDK 9 b153.

like image 4
Ravi Avatar answered Oct 13 '22 05:10

Ravi