Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getResourceAsStream() vs FileInputStream

I was trying to load a file in a webapp, and I was getting a 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?

like image 292
Vivin Paliath Avatar asked Feb 22 '10 00:02

Vivin Paliath


People also ask

What is getResourceAsStream?

getResourceAsStream() finds a resource with a given name.It returns a InputStream object or null if no resource with this name is found.

What is the difference between FileInputStream and InputStream?

There is no real difference. FileInputStream extends InputStream , and so you can assign an InputStream object to be a FileInputStream object. In the end, it's the same object, so the same operations will happen. This behavior is called Polymorphism and is very important in Object-Oriented Programming.

Do I need to close FileInputStream?

Yes, you need to close the inputstream if you want your system resources released back. FileInputStream. close() is what you need.


1 Answers

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's one) 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 so you can look "outside" the webapp context as well.

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.

See also:

  • Where to place and how to read configuration resource files in servlet based application?
  • What does servletcontext.getRealPath("/") mean and when should I use it
  • Recommended way to save uploaded files in a servlet application
  • How to save generated file temporarily in servlet based web application
like image 161
BalusC Avatar answered Dec 09 '22 08:12

BalusC