Reading files within an Executeable JAR file

I have been working a lot to learn how to load files that lie within the JAR file, but I just can’t get it working!!
No guide I’m trying works and I’m getting desperate. I’ll put an example of how the JAR file is set up below, could anyone tell me how to load the image “Star.jpg” please?


folder
	Loader.jar
		package
			Loader.class		<- The running code
		META-INF
			MANIFEST.MF
		resources
			Star.jpg		<- the image I want to load

If someone could give me a full method that can do this instead of saying “use this _____” I’d be very grateful

The way you should do this depends on the resource.

If it’s an image use:


/* Package structure
 * com.mypackage - Contains f.ex MyClass
 * res - Contains all resources
 */
URL myImageURL = MyClass.class.getResource("/res/myimage.png");
BufferedImage myImage = ImageIO.read(myImageURL);

But if its a file f.ex Settings.json: (I find it easier with streams, for some reason)


/* Package structure
 * com.mypackage - Contains f.ex MyClass
 * res - Contains all resources
 */
InputStream mySettingsStream = MyClass.class.getResourceAsStream("/res/settings.json");

//Option 1:
String mySettingsString = "";
int len;
byte b[];
while((len = mySettingsStream.available()) > 0) {
	b = new byte[len];
	r.read(b, 0, len);
	mySettingsString  += new String(b);
}

//Option 2:
int i = 0;
String mySettingsString = "";
while((i = mySettingsStream.read()) != -1 /*EOF*/) mySettingsString += (char)i;

//Close the stream when done
r.close();

@orogamo
THANK YOU!! It works like a charm. The only files I need to load in right now is text and image files so your solution covers everything. Later I’ll need to be able to do the same with music files (WAV files) and hopefully I’ll be able to adapt this to load those. I know how to play them if I just get a Stream open to them so if you have a particular way of opening a stream for music I’d be very happy.

Depends on which library you use.
If you use OpenAL(Like in LWJGL), this should do it:


InputStream myAudioStream = MyClass.class.getResourceAsStream("/res/myaudio.wav");

//You could either read all the bytes and:
WaveData.Create(myAudioBytes);

//Out just pass the InputStream:
WaveData.Create(myAudioStream);

I haven’t tested this code, i just read the documentation. So i hope it works :smiley:

EDIT:
If you want to use standard java libraries, something like this might work:


import javax.sound.sampled.*;
InputStream myAudioFileStream = MyClass.class.getResourceAsStream("/res/myaudio.wav");

AudioInputStream myAudioStream = AudioSystem.getAudioInputStream(myAudioFileStream);

AudioFormat myAudioFormat = myAudioStream.getFormat();

DataLine.Info myAudioInfo = new DataLine.Info(Clip.class, myAudioFormat);

Clip myAudioClip = (Clip) AudioSystem.getLine(myAudioInfo);

myAudioClip.open(myAudioStream);

myAudioClip.start();

reading text files can be done a lot easier:


Inputstream in = ...;
try(BufferedReader br = new BufferedReader(new InputstreamReader(in)))
{
   List<String> lines = new Arraylist<String>();
   String line;
   while((line = br.readLine()) != null)
      lines.add(line); 
}

No love for Scanner?


Scanner s = new Scanner(/* resource */);
List<String> lines = new Arraylist<String>();
while(s.hasNextLine())
    lines.add(s.nextLine());

Best thing is it has next() methods, e.g. nextInt(). Also has some regex ability.

Also if Java 7 is applicable, Files is great:


List<String> lines = Files.readAllLines(Paths.get(/* resource */), Charset.defaultCharset());

Thanks everyone for your help.
Does anyone happen to know how to write a text file to the same place as I’m been loading them from (the “res” folder inside the JAR)? It would be nice to be able to save a game easily.

As far as I know that is not directly possible.
But considering a Jar is simply a Zip file, this should/may be possible if you use a ZIP library for java to read and write to the jar.

[b]I do not recommend writing to the jar file, instead use

System.getProperty("user.home") + "/GameName"

or something similar.
And write your files there instead. [/b]