Java can't find file when running through Eclipse

derekerdmann picture derekerdmann · May 8, 2010 · Viewed 84.9k times · Source

When I run a Java application that should be reading from a file in Eclipse, I get a java.io.FileNotFoundException, even though the file is in the correct directory. I can compile and run the application from the command line just fine; the problem only occurs in Eclipse, with more than one project and application. Is there a setting I need to change in the run configurations or build paths to get it to find the file correctly?

Answer

Stephen C picture Stephen C · May 8, 2010

The problem is most likely that your application is using a relative pathname. As @BalusC says, relative pathnames can be problematic. But IMO, he goes way too far when he says "[y]ou should never use relative paths in java.io stuff".

When an application opens a file using (for example) the FileInputStream(File) constructor, relative pathnames are resolved relative to the "current directory" in a process described as follows in the javadoc for File.getAbsolutePath().

[...] Otherwise this pathname is resolved in a system-dependent way. On UNIX systems, a relative pathname is made absolute by resolving it against the current user directory. On Microsoft Windows systems, a relative pathname is made absolute by resolving it against the current directory of the drive named by the pathname, if any; if not, it is resolved against the current user directory.

So immediately, we see that the notion of "current directory" has different nuances on Windows and UNIX platforms. The second issue is that in pure Java you cannot definitively find out what the current directory is, and you certainly cannot change it for the current JVM using pure Java. (When the JVM starts, the "user.dir" system property is set to the current directory, but there is nothing stopping an application from changing the property so you cannot entirely rely on it. Furthermore, changing "user.dir" only changes the way that the empty path is resolved, not relative paths in general.)

So what should you do about this?

  • One option is to use absolute pathnames to refer to files. This is reliable in (almost) all cases, but using absolute pathnames can be problematic if the user has to enter the pathname, or if you need to avoid hard-wired (or configured) absolute pathnames.

  • A second option is to use classpath relative pathnames and locate files relative to the application's installation directory. This works if that is what you need to do, but presents a problem if you need to pass a File to some library method. It also doesn't help if you are trying to find the user's application preferences. (In general, putting user preferences into the installation directory is a mistake ...)

  • A third option is to name a file relative to some absolute directory that you get from somewhere else; e.g. new File(System.getProperty("home.dir"), "foo/bar");.

  • The final option is to use relative pathnames, and assume that the user knowing what the current directory. For many applications that the user runs from the command line, this is the right solution.

In the particular case of Eclipse, there is a simple solution. Go to the "run configuration" that you are using to launch your application, open the "Arguments" tab, and click the "Other" radio button. Then enter an absolute pathname as the working directory for the launched application. When the child JVM is launched, it will have the specified working directory as its current directory.