Tip #13 java.io.File Surprises
Posted
by ByronNevins
on Oracle Blogs
See other posts from Oracle Blogs
or by ByronNevins
Published on Thu, 10 Nov 2011 18:53:11 -0600
Indexed on
2011/11/11
18:10 UTC
Read the original article
Hit count: 455
/Sun
There is an assumption that I've seen in code many times that is totally wrong. And this assumption can easily bite you. The assumption is:
File.getAbsolutePath and getAbsoluteFile return paths that are not relative.
Not true! Sort of. At least not in the way many people would assume. All they do is make sure that the beginning of the path is absolute. The rest of the path can be loaded with relative path elements. What do you think the following code will print?
public class Main {
public static void main(String[] args) {
try {
File f = new File("/temp/../temp/../temp/../");
File abs = f.getAbsoluteFile();
File parent = abs.getParentFile();
System.out.println("Exists: " + f.exists());
System.out.println("Absolute Path: " + abs);
System.out.println("FileName: " + abs.getName());
System.out.printf("The Parent Directory of %s is %s\n", abs, parent);
System.out.printf("The CANONICAL Parent Directory of CANONICAL %s is %s\n",
abs, abs.getCanonicalFile().getParent());
System.out.printf("The CANONICAL Parent Directory of ABSOLUTE %s is %s\n",
abs, parent.getCanonicalFile());
System.out.println("Canonical Path: " + f.getCanonicalPath());
}
catch (IOException ex) {
System.out.println("Got an exception: " + ex);
}
}
}
Output:
Exists: true
Absolute Path: D:\temp\..\temp\..\temp\..
FileName: ..
The Parent Directory of D:\temp\..\temp\..\temp\.. is D:\temp\..\temp\..\temp
The CANONICAL Parent Directory of CANONICAL D:\temp\..\temp\..\temp\.. is null
The CANONICAL Parent Directory of ABSOLUTE D:\temp\..\temp\..\temp\.. is D:\temp
Canonical Path: D:\
Notice how it says that the parent of d:\ is d:\temp !!!The file, f, is really the root directory. The parent is supposed to be null.
I learned about this the hard way! getParentXXX simply hacks off the final item in the path. You can get totally unexpected results like the above. Easily.
I filed a bug on this behavior a few years ago[1].
Recommendations:
(1) Use getCanonical instead of getAbsolute. There is a 1:1 mapping of files and canonical filenames. I.e each file has one and only one canonical filename and it will definitely not have relative path elements in it. There are an infinite number of absolute paths for each file.
(2) To get the parent file for File f do the following instead of getParentFile:
File parent = new File(f, "..");
[1] http://bt2ws.central.sun.com/CrPrint?id=6687287
© Oracle Blogs or respective owner