Amal
Amal

Reputation: 75

Empty File constructor is neither file nor directory

What is the difference between the following two methods for creating a file?

new File(System.getProperty("user.dir"));
new File("");

Java identifies the first one as a directory, and the second one's neither a file nor a directory! Why is that the case?


Code:

public class MainClass {
    public static void main(String[] args) throws Exception {       
        System.out.println("File Created with CurrentDir taken From System Props");
        File f1 = new File(System.getProperty("user.dir"));
        System.out.println("Absolute Path: " + f1.getAbsolutePath());
        System.out.println("isDirectory: " + f1.isDirectory());
        System.out.println("isFile: " + f1.isFile());

        System.out.println();

        System.out.println("File Created with Empty String Path");
        File f2 = new File("");
        System.out.println("Absolute Path: " + f2.getAbsolutePath());
        System.out.println("isdirectory: " + f2.isDirectory());
        System.out.println("isFile: " + f2.isFile());       
    }
}

Output:

File Created with CurrentDir taken From System Props
Absolute Path: D:\Java Workspace\my_Workspace\JavaTest
isDirectory: true
isFile: false

File Created with Empty String Path
Absolute Path: D:\Java Workspace\my_Workspace\JavaTest
isdirectory: false
isFile: false

Upvotes: 5

Views: 1652

Answers (4)

Zabuzard
Zabuzard

Reputation: 25903

Explanation

It may seem a little non-intuitive but actually that's just how the class is supposed to work according to its documentation. It's called empty abstract pathname in the documentation:

The empty abstract pathname has no prefix and an empty name sequence.

And from your constructor File#File(String):

Creates a new File instance by converting the given pathname string into an abstract pathname. If the given string is the empty string, then the result is the empty abstract pathname.

So the File class actually interprets the empty name as actual name. When you test File#isDirectory() or File#isFile() it thus checks if there exists a file or directory like

D:\Java Workspace\iTAW_Workspace\JavaTest\<empty>

Note the <empty> which I wrote to indicate that it actually searches for a file here with the empty name. Obviously such a file can not exist, thus the result will always be false. So again, it does not check

D:\Java Workspace\iTAW_Workspace\JavaTest\

but rather the empty file in this directory, which does not exist.

Unfortunately you don't see this when using the File#toAbsolutePath() method as there is no representation for an empty name.


NIO

Note that the class File and everything related to it is outdated. Nowadays file IO is done using NIO revolving around Files, Paths and Path. This API is much more cleaner and more intuitive. It will also work as intended on your current example:

Files.isDirectory(Paths.get("")); // true

Take a look at the documentation for more.

Upvotes: 2

Michal
Michal

Reputation: 1010

new File("") creates new file with relative (empty) path. As this file doesn't exist both isDirectory() and isFile() return false (corresponds to javadoc).

From javadoc

boolean java.io.File.isDirectory()

...

Returns: true if and only if the file denoted by this abstract pathname exists and is a directory; false otherwise

The same is true for isFile(). and as long as your file doesn't exist both methods return false.

Upvotes: 1

vincrichaud
vincrichaud

Reputation: 2208

You need to make the difference between the Java object File and a file actually present on your computer.

In the first case : new File(System.getProperty("user.dir")). You create a Java object File and give him a path : System.getProperty("user.dir"). Later when you call the function .getAbsolutePath() it returns you the path you gave. Then when you call .isDirectory() it tells you true because there is a directory corresponding to this Java object File.


In the second case, new File("") it creates a Java object File and you give it a path : "". Since the path given is not absolute, the system will resolve it as a relative from the user.dir path.

from documentation

A pathname, whether abstract or in string form, may be either absolute or relative. An absolute pathname is complete in that no other information is required in order to locate the file that it denotes. A relative pathname, in contrast, must be interpreted in terms of information taken from some other pathname. By default the classes in the java.io package always resolve relative pathnames against the current user directory. This directory is named by the system property user.dir, and is typically the directory in which the Java virtual machine was invoked.

Later when you call the function .getAbsolutePath() it returns you the path you gave, so the path to user dir + empty string : D:\Java Workspace\iTAW_Workspace\JavaTest\<empty>. Then when you call .isDirectory() it tells you false because there is no directory corresponding to this path. (same reason for isFile())

Upvotes: 1

dontlookatme
dontlookatme

Reputation: 21

Creating a file with empty string results to creating a File instance which actually does not exist and its absolute pathname is "empty abstract pathname".

-> That's why the second one's neither a file nor a directory for you.

The reason behind that, a maybe little bit confusing output for you, is definition located in javadocs:

If this abstract pathname is the empty abstract pathname then the pathname string of the current user directory, which is named by the system property user.dir, is returned.

You can find more about this topic here https://docs.oracle.com/javase/6/docs/api/java/io/File.html

Upvotes: 2

Related Questions