Loading a Bufferedimage

To access resources from a folder that is alongside the top sources package, use this: [icode]ArtResources.class.getClassLoader().getResourceAsStream(filename);[/icode]

Where filename = [icode]“resources/textures/walltest.png”[/icode]

This worked for me in a quick test in NetBeans, including when exported as a Jar.

Capitalize folders, etc. as you see fit.

(Directory structure I used:)
TimeStrips
src
focus
ArtResources.java
resouces
textures
walltest.png

For more info: StackOverflow

[Edit] : Problem solved. Sorry for the unnecessary post.

/*Hmm. In the end I stuck with the class.getResource() method. It worked fine, I even added some .wav files for good measure, until I tried to export. And then, nothing, when the .jar is run, an unsized frame starts and that’s it. I guess the resources aren’t included, and in fact, the .jar only contains the .class files, no images, no sounds.

I tried implementing your method instead, with separate images and sounds folders, as I thought the files would then be added on export, but it fails to load the sounds. I’m guessing that I’m unable to reset the classpath after having loaded images, and that it’s trying to load sounds starting from the images folder.

I don’t mind which method I use, but I’d like a properly running .jar. Sorry, looks like I’ll need a bit more help on this one.*/

Actually, I have another question (sorry) : is the relative filepath I provided above valid for all platforms ?

I exported a .jar recently and it seemed to work on mac and windows distributions, but linux distributions wouldn’t load images and sounds ? Somebody suggested I change the first ‘/’ to ‘./’ but that didn’t change anything.

I’ve done a bit of searching, and though there are some topics on similar matters, none seem to focus on this particular aspect of exports, to my knowledge.

Jar resources are located using URLs not file names. They are part of a package, not a folder. The resource URLs’ root is the unnamed default package, so it is better to use absolute paths starting with “/” than a relative path. (Again, it is a URL within your project, not a URL within the entire hard drive.) The resources can go in the same place as your source code in your IDE. The capitalization must be correct. The URL should be in the form “/firstpackage/secondpackage/third/fourth/no/real/project/has/this/many/subpackages/filename.extension”. Package names should be all lower case just because that is convention. The capitalization of the resource name does not matter as long as it matches.

If you want a better answer you should post the error message, values of variables during execution (use println or a debugger), and the source code.

Unless I’m mistaken, the method above uses URLs, I just confusingly call my variable ‘filename’.

The piece of code that seems to be the problem is the one in my first post (and a similar bit for sounds).

My files are located in the /bin folder, in two separate folders, images and sounds. The .class files are in /bin/seconds/focus.

When I export and manually add the files in separate folders beside the .jar, it runs fine -except on Linux distributions, where I get this error, which leads me to believe the files aren’t detected :

Exception in thread “main” java.lang.ExceptionInInitializerError
(…)
Caused by: java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(ImageIO.java:1388)
at seconds.focus.gui.Images.loadBitmap(Images.java:36)
at seconds.focus.gui.Images.(Images.java:13)

I’m probably not doing something right here, but if I add the files to the .src folder and export them, they appear in the .jar but still don’t seem to be detected, which is strange…

What is the exact value of this “filename” variable and the exact location of the file within the jar. Note the emphasis on exact. Cut and paste the path if required so we get the correct capitalization, this is no time for vagueness.

filename is (in the case of the first image I load) : /images/title.png
(I changed layouts and names some)

Layout is like this :

bin
images
title.png

seconds
focus
gui
Display.class (contains main)
Images (loads Bitmaps)
Sound (loads sounds)
sounds

When I export it as is, the images and sounds folders aren’t added to the .jar. So I add them and place them next to the .jar. Then everything works fine, except on Linux (why it doesn’t work I don’t understand). I would like it to work on Linux.

I hope this is clear enough.

I don’t just link topics for shits and giggles you know. Although the link directs you to my post since I just copy pasted it from my history - the idea is to read the whole topic to understand the context.

There’s a difference between class.getResource() and class.getClassLoader().getResource().

If you’d bother to read the topic and think for a second you might, god forbid, actually learn something.


http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResource(java.lang.String)

Resources go in the src folder or they won’t get put in the jar.

I suggest you go ahead and read the topic as well.

I’m curious what you mean by “… the images and sounds folders aren’t added to the .jar. So I add them …”

Are you using Eclipse? Both source code and resources should be in a subfolder to src (if you are using Eclipse).[EDIT: corrected thanks to jonjova’s note below.]

If you use “Export” “Jar file” (not “Runnable JAR file”) then the screen “Jar File Specification” comes up with an expandable directory tree. If the folder with the resources is not clicked, you can select it at that stage. Maybe that is what you are already doing. Just confirming.

I found this section of the java tutorials helpful, even though it mostly talks about loading images for Icons. It has examples of several different loading scenarios:
see: Loading Images Using getResource
http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

My apologies, jonjava, but I was answering davidc’s question.

And I have looked at the first topic you mentioned (but not all the others -yet). However, it does not seem to answer my question regarding Linux builds and why my method works EXCEPT for Linux builds.

I am looking more into the topics right now. Sorry if I’ve unintentionally annoyed you.

From your OP it looks like you’re using class.getResource() as opposed to getClassLoader().getResource() and considering your reply to davidc you’re using a forward slash at the beginning of your filename:

Now if you take a look at what it says on the class.getResource() API (and how it significantly differs from getClassLoader().getResource()) you will notice this:

Basically you’re probably using absolute paths which is never good. You want to use relative paths that encapsulate OS differences.

Also, having stuff inside the ‘src’ directory is in no way a prerequisite of having your resources exported inside a jar file.

All right. So using this new structure, taking inspiration from your other topic :

bin
res
sounds
explosion.wav
images
title.png
src

public static Bitmap title = loadBitmap(“title.png”);

with loadBitmap containing :
BufferedImage img = ImageIO.read(Images.class.getClassLoader().getResourceAsStream(filename));

This is a relative path, yes ?

It works fine for images, which is nice.
However, it fails to do so for sounds afterwards, and I don’t understand why :

public static Sound shoot = loadSound(“shoot.wav”);
AudioInputStream ais = AudioSystem.getAudioInputStream((Sound.class.getClassLoader().getResourceAsStream(filename)));

[Edit] : Something I’d forgotten to mention : I hadn’t added my res folder to the build path as a source folder. However, when I did so, images stopped working. Removing the folder from the build path didn’t start making the images load properly as before, so there’s some otehr subtlety going on I don’t know about, apparently.

Normally I try to be as precise as possible. This time I said “the src folder” because I thought “a source folder” would be a little too complicated in this context. :persecutioncomplex:

However I did find out that ClassLoader’s getResource does not treat paths correctly (the leading / must be omitted).

I would recommend using absolute paths for resources because you want to uniquely identify a resource and you control the absolute path to your resource. (Unlike filesystems.) Its simpler if you use absolute paths so you wont have to move resources with your source code or fix a path every time if it happens to get passed between code in different packages.

No it is absolute because of the way ClassLoader works…

[quote]It works fine for images, which is nice.
However, it fails to do so for sounds afterwards, and I don’t understand why

[Edit] : Something I’d forgotten to mention : I hadn’t added my res folder to the build path as a source folder. However, when I did so, images stopped working. Removing the folder from the build path didn’t start making the images load properly as before, so there’s some otehr subtlety going on I don’t know about, apparently.
[/quote]
It should not have worked in the first place. Are you sure you are not using files? Or did you put res inside the src folder and then try to add res as a source folder?

My bad, the images were also stored elsewhere.
Anyways, I’m pretty tired right now. I’ll read up more on it tomorrow and hopefully be able to work things out a bit more than I am right now. Thank you for your help, anyway, all of you.

http://www.java-gaming.org/user-generated-content/members/54159/frogs.jar

Works for me on windows and linux.

import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Main {

	BufferedImage image;
	Clip clip;

	public Main() {
	}

	private void load() {
		System.out.print("Loading image... ");
		try {
			URL url = this.getClass().getClassLoader()
					.getResource("art/eastwood.jpg");
			image = ImageIO.read(url);
			System.out.println("Success.");
		} catch (Exception e) {
			System.out.println("Failed.");
		}

		System.out.print("Loading sound... ");
		try {
			URL url = this.getClass().getClassLoader()
					.getResource("snd/water-flowing.aif");
			clip = AudioSystem.getClip();
			AudioInputStream ais = AudioSystem.getAudioInputStream(url);
			clip.open(ais);
			System.out.println("Success.");
		} catch (Exception e) {
			System.out.println("Failed.");
		}
	}

	private void show() {
		JFrame frame = new JFrame("Frogs");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);

		ImageIcon icon = new ImageIcon(image);
		JLabel label = new JLabel(icon);

		frame.add(label);

		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		clip.loop(-1);
	}
	
	private void close() {
		clip.close();
	}

	public static void main(String[] args) {
		Main m = new Main();
		m.load();

		try {
			m.show();
			Thread.sleep(10*1000);
		} catch (Exception e) {
			System.out.println("Headless Mode Exception.");
		}
		m.close();
		System.exit(0);
		System.out.println("Closing.");
	}
}

Wow. You didn’t need to go so far as to spend some time making an example. But thanks a bunch for the help.

[Edit] : Success. I get a proper .jar, it seems. I had to clean up another issue with sounds, but it works. Phew. Sorry for being such a blockhead, anyway.