FileNotFound
exception when I used FileInputStream
. However, using the same path, I was able to load the file when I did getResourceAsStream()
. What is the difference between the two methods, and why does one work while the other doesn't?
The
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the
Another alternative in webapps is the
The
java.io.File
and consorts acts on the local disk file system. The root cause of your problem is that relative paths in java.io
are dependent on the current working directory. I.e. the directory from
which the JVM (in your case: the webserver) is started. This may for
example be C:\Tomcat\bin
or something entirely different, but thus not C:\Tomcat\webapps\contextname
or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname
. You can learn about the current working directory the following way:System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File
API instead of relative paths. E.g. C:\full\path\to\file.ext
. You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the
src
folder and the "build path" respectively). This way you can grab them with help of the ClassLoader
by ClassLoader#getResource()
or ClassLoader#getResourceAsStream()
.
It is able to locate files relative to the "root" of the classpath, as
you by coincidence figured out. In webapplications (or any other
application which uses multiple classloaders) it's recommend to use the ClassLoader
as returned by Thread.currentThread().getContextClassLoader()
for this.Another alternative in webapps is the
ServletContext#getResource()
and its counterpart ServletContext#getResourceAsStream()
. It is able to access files located in the public web
folder of the webapp project, including the /WEB-INF
folder. The ServletContext
is available in servlets by the inherited getServletContext()
method, you can call it as-is.The
FileInputStream
class works directly with the
underlying file system. If the file in question is not physically
present there, it will fail to open it. The getResourceAsStream()
method works differently. It tries to locate and load the resource using the ClassLoader
of the class it is called on. This enables it to find, for example, resources embedded into jar
files.
FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. Usually in a web container, this is something like the
getResourceAsStream() will load a file path relative from your application's classpath.
bin
folder.getResourceAsStream() will load a file path relative from your application's classpath.
classname.getResourceAsStream() loads a file
via the classloader of classname. If the class came from a jar file,
that is where the resource will be loaded from.
FileInputStream is used to read a file from the filesystem.
FileInputStream is used to read a file from the filesystem.
1 comment:
attractive piece of information, I had come to know about your blog from my friend arjun, ahmedabad,i have read atleast eleven posts of yours by now, and let me tell you, your website gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new posts, once again hats off to you! Thanks a lot once again, Regards, Difference Between Classpath and Path
Post a Comment