getResourceAsStream() vs FileInputStream
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
What is the difference between getResourceAsStream(Words.txt) and FileInputStream(./src/package/Words.txt)?
At the moment, you're on your developer workstation, and are probably running your app from your IDE. Tomcat happens to be started from the IDE project root directory, and thus using
new FileInputStream("./src/package/Words.txt")
allows reading the file stored in your project src
directory.
But that's not how the project will be run in production. In production, you'll have a Tomcat server started from a totally different directory, using a shell script. And the production server won't have the source project at all. All it will have is Tomcat, and the war file constituting the artifact built from the project.
So there will be no src
directory at all, and the file Words.txt
won't even be anywhere on the file system. It will only be en entry of the war file (which is in fact a zip file), located under WEB-INF/classes/package
along with the .class
files produced by the compiler from your Java source files.
So, in order to be able to read that "file", you can't use file IO: the "file" doesn't exist in the file system. You need to use the ClassLoader that will locate the "file" inside the war file and load it from there.
That will also go fine during development, when the app is run from an exploded war structure: the class loader will find the class under the target directory used by your IDE to store the class files and resource files.
Note that what you need to load that resource, if it's in the package com.foo
and MyClass is in that same package, is
MyClass.class.getResourceAsStream("Words.txt")
or
AnyOtherOfYourClassesWhateverThePackageIs.class.getResourceAsStream("/com/foo/Words.txt")
or
classLoader.getResourceAsStream("com/foo/Words.txt")
FileInputStream vs ClassPathResource vs getResourceAsStream and file integrity
I had the same issue, you probably have a problem with maven filtering.
This code load the file from source, unfiltered
InputStream is = new FileInputStream("C:/.../src/main/resources/template.xlsx");
This code load the file from the target directory, after maven has filtered the content
InputStream is = getClass().getResourceAsStream("/template.xlsx");
You should not filter binary files like excel and use two mutually exclusive resource sets as described at the bottom of this page maven resources plugin
Replacing FileInputStream with getResourceAsStream
Check if is
is null
after doing getResourceAsStream
. If it is, the resource has not been found. In this case check the path to the file, it is relative to your classpath. I don't know your project setup but I would try to simply use "/public.key"
…
When to use getResourceAsStream method?
getResourceAsStream
searchs you classpath for the given file/resource and it can also provide InputStreams
of resources from inside a JAR.
So, if your properties exist in some folder in the physical filesystem (e.g. user folder, ...) use FileInputStream
and if the file is embedded in your classpath (e.g. as a resource inside the JAR) use getResourceAsStream
.
ObjectInputStream happy with FileInputStream, not happy with getResourceAsStream
EFBFBD
is a UTF-8 representation of Unicode replacement character U+FFFD. So, it looks like file was passed through some encoding conversion process.
Maven can be a suspect, especially its resource filtering feature.
Related Topics
How to Create a Java String from the Contents of a File
Loop Doesn't See Value Changed by Other Thread Without a Print Statement
Read/Write to Windows Registry Using Java
Infinite Recursion With Jackson Json and Hibernate JPA Issue
Why Is Java Vector (And Stack) Class Considered Obsolete or Deprecated
Java: Maintaining Aspect Ratio of Jpanel Background Image
What Causes Error "No Enclosing Instance of Type Foo Is Accessible" and How to Fix It
Java - Sending Http Parameters Via Post Method Easily
Generating All Permutations of a Given String
What Are the -Xms and -Xmx Parameters When Starting Jvm
When Do You Use Java'S @Override Annotation and Why
What Is the Point of the Diamond Operator (≪≫) in Java
Setting the Default Java Character Encoding
Retain Precision With Double in Java
Run Java Class File from PHP Script on a Website
How to Create Recyclerview With Multiple View Types