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

Filed under:

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

Related posts about /Sun