FAQ: cannot find the resource/file

Having trouble finding your resources when your exported your files to a JAR?

Step 1: never use [icode]File[/icode] or [icode]FileInputStream[/icode] to lookup resources in a JAR

Didn’t that quite solve your problem?

Step 2: put this code in your application:

Now it’s time to figure out why your resource cannot be found:

Step 3: insert this line where error occurs


ClassLoaderDummy.searchResource("res/images/sprite.jpg");

Example input:


	public static void main(String[] args) throws IOException {
		ClassLoaderDummy.searchResource("sprite.jpg");
		ClassLoaderDummy.searchResource("images/res/Sprite.JPG");
		ClassLoaderDummy.searchResource("images/sprite.jpg");
		ClassLoaderDummy.searchResource("res/images/sprite.jpg");
		ClassLoaderDummy.searchResource("res/images/Sprite.jpg");
		ClassLoaderDummy.searchResource("sprite.png");
		ClassLoaderDummy.searchResource("huh.png");
	}

Example output:


[ClassLoaderDummy] SEARCHING: "sprite.jpg"
[ClassLoaderDummy] FOUND: mislocated, similarly named resource:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "images/res/Sprite.JPG"
[ClassLoaderDummy] FOUND: mislocated resource:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "images/sprite.jpg"
[ClassLoaderDummy] FOUND: mislocated, similarly named resource:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "res/images/sprite.jpg"
[ClassLoaderDummy] FOUND: similarly named resource:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "res/images/Sprite.jpg"
[ClassLoaderDummy] FOUND: similarly named resource:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "sprite.png"
[ClassLoaderDummy] FOUND: similarly named resource with different extension:
[ClassLoaderDummy]                "res/images/Sprite.JPG"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/res/images/Sprite.JPG");

[ClassLoaderDummy] SEARCHING: "huh.png"
[ClassLoaderDummy] FAILED: failed to find anything like
[ClassLoaderDummy]                "huh.png"
[ClassLoaderDummy]          in all classpath entries:
[ClassLoaderDummy]                "D:\workspace\workspace4\Misc\bin"
[ClassLoaderDummy]                "D:\workspace\workspace4\LibBase\bin"
[ClassLoaderDummy]                "D:\workspace\workspace4\LibComponents\bin"
[ClassLoaderDummy]                "D:\workspace\workspace4\LibMedia\bin"
[ClassLoaderDummy]                "D:\workspace\workspace4\LibMedia\lwjgl_util.jar"
[ClassLoaderDummy]                "D:\workspace\workspace4\LibMedia\lwjgl.jar"

Question:

Should one use [icode]ClassLoaderDummy.class.getResource()[/icode], [icode]ClassLoaderDummy.class.getClassLoader().getResource()[/icode], [icode]ClassLoaderDummy.class.getResourceAsStream()[/icode], or [icode]ClassLoaderDummy.class.getClassLoader().getResourceAsStream()[/icode]?

As the suggested path starts with a “/”, it doesn’t really matter how you call [icode]getResourceAsStream(path)[/icode]

These will (for 99.9% of configurations) all yield the same result:


String path = "/res/anything/sprite.jpg";
InputStream in1 = MyClass.class.getResourceAsStream(path);
InputStream in2 = myInstance.getClass().getResourceAsStream(path);
InputStream in3 = myInstance.getClass().getClassLoader().getResourceAsStream(path);
InputStream in4 = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);

[quote]Step 1: Never use File or FileInputStream to lookup resources in a JAR
[/quote]
But otherwise otherwise it’s perfectly fine? Just not “to lookup resources in a JAR”.
Also, why is that?

Yes, and because the jar is a zip file, the computer can’t read normally through the file system. Files packed in a jar needs a special stream to read the data within.

Ah, I see, thanks.

I loaded a texture based on what you said:

		TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/images/sprite.jpg"));

The exception was :

Exception in thread "main" java.lang.RuntimeException: Resource not found: res/images/sprite.jpg
	at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)
	at imgtest.main(imgtest.java:12)

My ClassLoaderDummy code always outputs paths starting with “/”.

My bad, I didn’t follow Step 2. :-\

Now that I got that setup, your class tells me


[ClassLoaderDummy] SEARCHING: "res/space.png"
[ClassLoaderDummy] FOUND: mislocated resource:
[ClassLoaderDummy]                "space.png"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "C:\Users\Owner\workspace\FlubberSpace\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/space.png");

and I did use getResourceAsStream when I accessed it with the texture loader.

So… it works… right?

If not, what are you testing?

  1. probably loading the resource from within Eclipse (does it work?)
  2. loading the resource when launching a jar (does it work?)

If the answers are: 1. yes, 2. no, then run ClassLoaderDummy from the jar, and let it find the resource from that classpath.

It works fine in eclipse, just not when I export it. 2 is what I’m aiming for but It gives the same results.

So, the same? …when you run it from the jar, you get this?


[ClassLoaderDummy] SEARCHING: "res/space.png"
[ClassLoaderDummy] FOUND: mislocated resource:
[ClassLoaderDummy]                "space.png"
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                "C:\Users\Owner\workspace\FlubberSpace\bin"
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream("/space.png");

Really??

Did you read this carefully?

I don’t think I understand how to do that. Do I call the ClassLoaderDummy to searchfor it and export the jar with that class?

yes

It still doesn’t work. This is how I export it.

Export >> Runnable Jar >> COpy Libs to a folder near the jar >> finish >> open Jarsplice >> Add jar and jars from lib folder >> add natives >> input main class >>> create fat jar >> cmd can’t load resource

Should I just create a folder in the cdrive with all the images?

Ah, maybe It was my gameloop I think. the old flubberspace works fine. Hmm…

You have to run ClassLoaderDummy just prior to the line that attempts to load the resource.

Then run the program from the exported JAR, and post the output here (if you can’t resolve the issue yourself).

N.B.: the output you post must contain output from ClassLoaderDummy.




Old code example:


TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/images/sprite.jpg"));

New code example:


String path = "res/images/sprite.jpg";
ClassLoaderDummy.searchResource(path);
TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(path));

Output example you would post here:


[ClassLoaderDummy] SEARCHING: "res/images/sprite.jpg"
[ClassLoaderDummy] FOUND: .......... resource:
[ClassLoaderDummy]                ......
[ClassLoaderDummy]          in classpath entry:
[ClassLoaderDummy]                ......
[ClassLoaderDummy]          for access use:
[ClassLoaderDummy]                getResourceAsStream(..........);

Exception in thread "main" java.lang.RuntimeException: Resource not found: res/images/sprite.jpg
   at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)
   at imgtest.main(imgtest.java:12)