If you have old Java applications that use File
constructors for Windows drives,
avoiding File.listRoots()
,
you may want to read this Blog,
because that functionality changed a little bit in
Java 11.
Unix systems are not affected.
Why not use File.listRoots()
?
This method didn't exist in Java 1.1. Moreover, in times of floppy-drives,
this call caused periodical dialogs appearing in case no floppy was inserted.
Java 1.2 listRoots()
was not really usable for listing Windows drives,
a still persisting problem are network drives that answer very slowly.
You will want to let run each of those drive-explorations in a background thread,
integrating them just when they answer within a configured timeout.
Windows versus Unix File-System
The difference between Windows and Unix file systems is that Unix has exactly one file-system root ("/"), while Windows has as many roots as disks and drives of any kind are available ("A:", "B:", "C:", .... "Z:"). The Windows path-separator is "\" (backslash), while Unix has "/" (slash).Constructor Test Results
In the following you find different calls to File
constructors,
and what properties they yield.
I was running these tests with Java 1.8 and 11 on Windows 8.1.
For comparability I also included the results from Ubuntu 18.04 Linux.
Click on the expand-controls below to see how constructors behave.
- Windows 8.1
- Java 1.8.0_25
- File drive = new File("C:")
-
exists() getName() getPath() getAbsolutePath() toString() true C: C:\Users\fred\eclipse-workspace\friwintest C: for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() false bin C:\bin C:\bin C:\bin false src C:\src C:\src C:\src
-
-
File drive = new File("C:\")
-
exists() getName() getPath() getAbsolutePath() toString() true C:\ C:\ C:\ for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true Program Files C:\Program Files C:\Program Files C:\Program Files true Users C:\Users C:\Users C:\Users true Windows C:\Windows C:\Windows C:\Windows
-
-
File drive = new File("\")
-
exists() getName() getPath() getAbsolutePath() toString() true \ C:\ \ for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true Program Files \Program Files C:\Program Files \Program Files true Users \Users C:\Users \Users true Windows \Windows C:\Windows \Windows
-
- File drive = new File("C:")
- Java 11.0.2
-
File drive = new File("C:")
-
exists() getName() getPath() getAbsolutePath() toString() true C: C:\Users\fred\eclipse-workspace\friwintest C: for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true bin C:bin C:\Users\fred\eclipse-workspace\friwintest\bin C:bin true src C:src C:\Users\fred\eclipse-workspace\friwintest\src C:src
-
-
File drive = new File("C:\")
-
exists() getName() getPath() getAbsolutePath() toString() true C:\ C:\ C:\ for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true Program Files C:\Program Files C:\Program Files C:\Program Files true Users C:\Users C:\Users C:\Users true Windows C:\Windows C:\Windows C:\Windows
-
-
File drive = new File("\")
-
exists() getName() getPath() getAbsolutePath() toString() true \ C:\ \ for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true Program Files \Program Files C:\Program Files \Program Files true Users \Users C:\Users \Users true Windows \Windows C:\Windows \Windows
-
-
File drive = new File("C:")
- Java 1.8.0_25
- Linux
- Java 1.8.0_25
- File drive = new File("/")
-
exists() getName() getPath() getAbsolutePath() toString() true / / / for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true bin /bin /bin /bin true usr /usr /usr /usr
-
- File drive = new File("/")
- Java 11.0.2
- File drive = new File("/")
-
exists() getName() getPath() getAbsolutePath() toString() true / / / for (String name: drive.list()) new File(drive, name);
exists() getName() getPath() getAbsolutePath() toString() true bin /bin /bin /bin true usr /usr /usr /usr
-
- File drive = new File("/")
- Java 1.8.0_25
new File("C:")
When expanding Windows -> Java 1.8 -> new File("C:")
,
you will see that the absolute path doesn't match expectations.
Instead of "C:\" it is the current working directory where my test-app was running.
Below Java 11 you need to use new File("C:\\")
, see next example.
Nevertheless, when you do new File("C:").list()
and
construct children with these names, and the drive as parent,
the constructed files will not exist,
because the list()
children were taken from current working directory!
Similar problems exist in Java 11, although the list-children actually exist in this version.
But look at the getPath()
result: "C:bin"
isn't a valid path!
new File("C:\\")
With "C:\\"
everything works fine, and it's the same for Java 1.8 and Java 11.
It's just the ugly file-separator in the name of the drive.
new File("\\")
This would be something similar to UNIX "/".
It works, but you don't get the drive name "C:"
from getPath()
.
By the way, toString()
still delegates to getPath()
,
they did not change that in Java 11.
Test Source Code
You could do such a test with the following example, compiling it with Java 1.8 and then running it with both 1.8 and 11 (JRE 1.8 will not run classes compiled with 11):
public class FileConstructorTest { public static void main(String [] args) { test("C:"); test("C:"+File.separator); test(File.separator); } private static void test(String driveName) { final File drive = new File(driveName); output(drive); for (final String name : drive.list()) output(new File(drive, name)); } private static void output(File file) { System.err.println( "exists="+file.exists()+ ", name="+file.getName()+ ", path="+file.getPath()+"</td>"+ ", absolutePath="+file.getAbsolutePath()+ ", toString="+file.toString()); } }
Keine Kommentare:
Kommentar veröffentlichen