I have something like the following project structure
-project
-src/main/java // source folder
-com.mypackage
-Utility.java
-some.properties
-src/main/resources // source folder
-configuration_files
-configuration_report.txt
I'm generating the jar
with Eclipse's Export
function. The above translates to a jar
with the structure:
-myjar.jar
-com
-mypackage
-Utility.class
-some.properties
-configuration_files
-configuration_report.txt
Within the Utility
class, I'm trying to get the InputStream
from configuration_report.txt
.
I was doing this (it's within a static
method):
Utility.class.getResourceAsStream("/configuration_files/configuration_report.txt");
which seems to be validated by the answer to this question, since the file is not in the same package as the class requesting it.
When I run it, however, it returns null
. Why?
Note that for the some.properties
file, I could do both
Utility.class.getResourceAsStream("/com/package/some.properties");
Utility.class.getResourceAsStream("some.properties");
and I would get the stream.
I'm running this from the command line if it makes any difference.
java [-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044] -cp myjar.jar MyMain
If I try to run it within Eclipse, it works...
Edit:
This code is relevant. With or without the preceding /
, it return null
String sourceFilePath = "/configuration_files" + File.separator + "configuration_report.txt";
InputStream in = Utility.class.getResourceAsStream(sourceFilePath);
The java. lang. Class. getResourceAsStream() finds a resource with a given name.It returns a InputStream object or null if no resource with this name is found.
getResourceAsStream , send the absolute path from package root, but omitting the first / . If you use Class. getResourceAsStream , send either a path relative the the current Class object (and the method will take the package into account), or send the absolute path from package root, starting with a / .
The getResourceAsStream method returns an InputStream for the specified resource or null if it does not find the resource. The getResource method finds a resource with the specified name. It returns a URL to the resource or null if it does not find the resource. Calling java.
After many tries, the solution comes down to this little javadoc entry for ClassLoader#getResource(String)
:
The name of a resource is a '/'-separated path name that identifies the resource.
The snippet I had originally posted would've worked
Utility.class.getResourceAsStream("/configuration_files/configuration_report.txt");
but I wasn't using /
, I was using File.separator
like in my edit:
String sourceFilePath = "/configuration_files" + File.separator + "configuration_report.txt";
thinking the class loader worked like OS specific File operations. The first /
was matched, but the File.separator
evaluated to \\
since I'm on Windows.
The javadoc for Class#getResource(String)
says more of the same.
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
As to why this worked on Eclipse, but not from the command line, I'm still unsure, but look at @andy's comment below.
This article gives is a good explanation of this situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With