8

I just want to read a file into my program. The file is located one directory above the working directory at "../f.fsh". So the following code runs correctly when I run it in the IDE

String name="../f.fsh";
InputStream is = getClass().getResourceAsStream(name);
InputStreamReader isreader=new InputStreamReader(is);//CRASHES HERE WITH NULL POINTER EXCEPTION
BufferedReader br = new BufferedReader(isreader);

but when I create a JAR file that has f.fsh zipped inside of it and run it, it crashes when creating the InputStreamReader, because the InputStream is null.

I've read a bunch of answers to questions about input streams and JAR files, and what I got out of it is that I should be using relative paths, but I am already doing that. From what I understand getResourceAsStream() can find files relative to the root of the project, that is what I want. Why does it not work in the JAR? What is going wrong, how can I fix it?

Does it have to do with the classpath? I thought that was only for including files external to the jar being run.

I have also tried, but still fail, when putting a slash in:

InputStream is = getClass().getResourceAsStream("\\"+name);

I looked at: How to get a path to a resource in a Java JAR file andfound that contents of a JAR may not necesarily be accesible as a file. So I tried it with copying the file relative to the jar (one directory up from the jar), and that still fails. In any case I'd like to leave my files in the jar and be able to read them there. I don't know what's going wrong.

Community
  • 1
  • 1
AAB
  • 674
  • 3
  • 14
  • 27

3 Answers3

11

You can't use .. with Class.getResourceAsStream().

To load a resource f.fsh in the same package as the class, use SomeClass.class.getResourceAsStream("f.fsh")

To load a resource f.fsh in a sub-package foo.bar of the package of the class, use SomeClass.class.getResourceAsStream("foo/bar/f.fsh")

To load a resource f.fsh in any package com.company.foo.bar, use SomeClass.class.getResourceAsStream("/com/company/foo/bar/f.fsh")

This is described in the javadoc of the getResource() method, although it lacks examples.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks for the response, I see what you are saying about adding a slash or not to the beginning. It does not work with ".."? It seems to undestand the ".." when I run it from eclipse. But it just is not compatible from the jar? Do you know why it is? – AAB Apr 16 '13 at 22:13
  • 1
    I'm even surprised it works when used out of a jar. The javadoc doesn't allow for .. to be used. It's just how it's designed. – JB Nizet Apr 17 '13 at 06:46
  • Just experienced the same issue. My guess would be that when executed from class files on disk the argument is simply sent (slightly parsed) to an OS function an therefore works even though not following protocol. This was tested with SE6 btw. – user Sep 15 '14 at 09:18
4

If .. works in Class.getResourceAsStream() while running from Eclipse, it's a bug in Eclipse. Eclipse and other IDEs implement custom class loaders to fetch resources from the project at runtime. It looks like the class loader implementation in Eclipse isn't performing all the necessary validations on input to getResourceAsStream() method. In this case the bug is in your favor, but you will still need to rethink how you structure your resources for your code to work in all cases.

Konstantin Komissarchik
  • 28,879
  • 6
  • 61
  • 61
  • Thanks, that makes sense. I changed my file locations and where my resources are located and it was able to get past this error in the jar. I would never have thought that Eclipse had a bug in my favor. Thank you so much! – AAB Apr 16 '13 at 22:56
0
  1. it's mandatory that the name of the file is CASE SENSITIVE
  2. it's mandatory to refresh (F5) the project explorer if the file is moved or copied outside Exclipse