dev
dev

Reputation: 1507

Access a file from within a jar on Windows

I am having trouble accessing a file within my Jar on Windows. I do not have this problem when I run it on Unix. I have created the jar both on Windows & Unix and it makes no difference. Either way it does not run on Windows.

I ran the jar -tf command on my jar and the class I am running from is located in: a/b/c/d/ClassOne.class. The class I am looking for is located in my base directory of the jar: ClassTwo.class

My code in this ClassOne looks like the following:

String path = File.separator + "myYAML.yml";
InputStream in = MetricCollector.class.getResourceAsStream(path);
InputStreamReader isr = new InputStreamReader(in);
BufferedReader input = new BufferedReader(isr);

My code breaks on the last line shown throwing a NullPointerException which I can only believe means it cannot find the path I have given it. However, this exact code works great on my debugger and on Unix when I run the jar.

I have also tested the following paths:

  1. "myYAML.yml"
  2. File.seperator + ".." + File.seperator + ".." + File.seperator + ".." + File.seperator + ".." + "myYAML.yml"
  3. ".." + File.seperator + ".." + File.seperator + ".." + File.seperator + ".." + "myYAML.yml"

all to no avail.

I have used the following Stack Overflow posts to get as far as I can, but they do not seem to have an answer for me: How to reference a resource file correctly for JAR and Debugging?, Accessing resources within a JAR file and Reading file from within JAR not working on windows

Any additional help I would be extremely grateful for. Thanks in advance.

Upvotes: 0

Views: 207

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279910

File.separator cannot work on Windows, it returns \. You need to use / as a separator regardless of the OS.

The Class#getResource(String) states

Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:

If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'. Otherwise, the absolute name is of the following form: modified_package_name/name

Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').

In other words, you must use /. This is further explained in the javadoc for ClassLoader.html#getResource(java.lang.String) to which Class#getResource delegates.

The name of a resource is a /-separated path name that identifies the resource.

If the resource is at the root of the classpath, use

InputStream in = MetricCollector.class.getResourceAsStream("/myYAML.yml");

Upvotes: 3

Related Questions