Using audio from resources in a jar file - java

I've managed to make resources finally get into the jar by using a class with inputstream getting resources from the class, and also adding the images and sounds to a folder within the project directory in eclipse and adding it to the buildpath.
With this images finally run from the within the jar. The same code using AudioinputStream instead of image.io works within the ide when you click run.
But from the jar file there are no sounds.
Here's the code in question
AudioInputStream audioIntStream = AudioSystem.getAudioInputStream(
Resourceloader.load("images/engine.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIntStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
title = ImageIO.read(Resourceloader.load("images/title.png") );
The images files from the same directory read from both ide and jar, while as said the audio file only runs from within ide not jar yet jar contains audiofile

Resource loading in Java can be complicated. However, the following code snippet is almost always what you want:
Thread.currentThread().getContextClassLoader.getResourceAsStream(
"path/to/resource/from/jar/root.file");
I use that snippet so often that I could type it in my sleep. I'd adjust your code above to use it to load your resources. However, if that doesn't cut it, I'd look into the following:
Check the resources after loading, and throw an Exception if they're null.
Open up your JAR as a ZIP file and ensure that the resource is actually at the path you have listed in your code, starting from the root of the JAR.
Use Ant or Maven to build your JAR, rather than Eclipse's GUI. This will help ensure that your JAR is always built in the same way and reduces the chances for manual mistakes. Using Maven and the standard Maven src/main/resources/ directory is highly recommended.

Related

Unable to reach resources folder when compiling from .jar to .exe using Launch4j

I made a small Java program for academic purposes, its main focus is to read some .txt files and present the information to the user. These files are present in the resources folder, under the src folder.
The program runs as intended when launched from Eclipse.
Using the Launch4j app I was able to successfully create an exe which runs fine and does what's intended, up until I try to read the .txt files I have in the resources folder, which appears not to be able to reach.
I'm guessing that when I launch the exe the run time path would change to where the exe was created, so I created the program in a desktop folder and specified this path in the program, but that doesn't seem to solve the situation.
As an alternative, I moved the .txt files out of the program and once again created the exe in a desktop folder with said .txt files, linked the program to this path and once again it didn't work.
The command used to get the .txt files is:
Files.readAllLines(Paths.get(doc)).get(line)
And doc is simply the path to the intended .txt file.
It's worth noting that I have no previous experience in Java and throughout the development of the program I tried my best to use commands I'd fully understand and to keep it as simple as possible. I hope the solution can be along these lines! I'm very confident this must be a rookie mistake, but I can't seem to find the solution to this specific problem anywhere.
The paths to files in Eclipse are different than the paths to files in an .exe or JAR file.
I will let this other user explain it because I am lazy :p
Rather than trying to address the resource as a File just ask the
ClassLoader to return an InputStream for the resource instead via
getResourceAsStream:
InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
As long as the file.txt resource is available on the classpath then
this approach will work the same way regardless of whether the
file.txt resource is in a classes/ directory or inside a jar.
The URI is not hierarchical occurs because the URI for a resource
within a jar file is going to look something like this:
file:/example.jar!/file.txt. You cannot read the entries within a jar
(a zip file) like it was a plain old File.
This is explained well by the answers to:
How do I read a resource file from a Java jar file?
Java Jar file: use resource errors: URI is not hierarchical
The original post is here, all credit to its author.
Fixing your URL should let you read from that file when you are using the .exe.
EDITED FOR CORRECTION. Thanks #VGR (see comments) for correcting my mistake.

Location of ogg files with EasyOgg

After looking at a couple of audio libraries, I settled on EasyOgg. Most of the samples report that you play sounds like this:
new OggClip("mysfx.ogg").loop();
This crashes with Couldn't find: mysfx.ogg at runtime. I tried several things:
Plain filename
Relative path from my project root directory
Forward-slashes and backslashes
I can't figure out where exactly the file goes, and how to specify the name. It seems like they should be somehow embedded in my application JAR. (I just have them sitting on the file system.)
I fiddled around with it for a while and came up with a solution using InputStreams:
FileInputStream stream = new FileInputStream("file.ogg");
OggClip clip = new OggClip(stream);
This works without including the files in the jar.
I'm not familiar with EasyOgg, but the first thing I would do is pass in the complete location to the file as a sanity check.
new OggClip("/home/someuser/audio/mysfx.ogg").loop();
If you can't count on java being run from the same location every time, you can use an environment variable to point to the location that your files are sitting in.
new OggClip(System.getenv("MY_APP_HOME") + "/audio/mysfx.ogg").loop();
As far as getting to a resource from inside a jar file, have you tried getResource()?
See: Access file in jar file?
I discovered that the OGG files need to be in the JAR file. This is clear from the working zip samples I found on the interwebz.
To use Gradle to zip up every .ogg file in audio, I add this to my jar task:
from fileTree(dir: '.', include: 'audio/**/*.ogg')
This works, except when I debug from Eclipse. A better solution is to create a separate project (I called mine EmbeddedResources) which creates a JAR that only contains .ogg files. Then, I reference this project from my game project, and I'm done.

Why does an image path no longer work once I compile my java files into a jar file?

I have a relatively basic java program which uses a system tray icon. The path I was using while writing the code is as follows "../images/logo.png". However, when I compile it into a jar file, the image does not show up in the system tray. Instead, if I change the path to "./images/logo.png", then the image shows up in the system tray when it's in the jar file form, but not while I'm testing.
It's not a major issue. However, I am curious to know why this inconsistency occurs.
When you package your program into a .jar file, your build is most likely copying the image into the same directory as the .jar file. However, when debugging in your ide, your image file lies one directory below.
Another possibility is that you are simply setting your Working Directly differently in the two scenarios.
Incidentally, you might be interested in embedding the image in your jar file, see:
https://stackoverflow.com/a/1096491/24954
This answer depends on two things. If the image file is embedded or not.
Embedded Resource
Once you have Jar'ed your application and the images are emebbed inside the application, normal file access methods will no longer work.
Trying to do something like...
new ImageIcon("../images/logo.png");
or
new File("../images/logo.png");
Won't work. This is because the resource is no longer a file within the context of the file system (it's actually a Zip entry in the Jar).
Instead, you need to use Class#getResource which will return a URL to the embedded resource.
new ImageIcon(getClass().getResource("../images/logo.png"));
Will work better. In general though, it is recommended to use an absolute path to the resources new ImageIcon(getClass().getResource("/images/logo.png")); as it's generally more difficult to break (IMHO)
External Resource
The path to the image is relative to the execution point of the application.
In development, you may have had to move up a directory (out of the src folder presumably) to find the image resource. This will mean that you will need to store you Jar file in a folder that would require it step up one level before it could find the image resource.
If you can, it's generally better to embedded the resource within the Jar where possible. It makes it easier to deploy as you reduce the number of files you need to package and makes it (a little) harder for the user to mess with it ;)

Find a resource both in .jar and eclipse with the same String computation

I want to get the path to a resource for ImageIO to read out a BufferedImage from some .png s.
While developing the project I use a relative path to "/bin/stuff/icons/image.png" , but this will definetly not work when I put everything together into a .jar file, so I need a way to get the path to these resources both while testing in eclipse and when later running it within a .jar .
After a lot of trying out both finding the file and getting the input stream to the file I came to the conclusion that this approach works every time:
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(path)
BufferedImage image = ImageIO.read(in)
Where path is
"projectName/resourceFolder/" + nameOfResource.stuff
as found in the src directory of the eclipse project.
E.g.
"myProject/images/icon.png"
When getting only the resource and then getting the path of the resource to link to a file, you will get FileNotFoundExceptions when using a .jar (but not while testing with eclipse, so one should be warned to think that his code works).
And - no - I don't save images in the bin/ - but they are copied to this directory and thus I find them there while testing. Now everything seems to be working.
Don't put anything under the bin directory in Eclipse: if you run a clean on the project it will be erased.
What you can do is to define a new source folder like resources, and put the image there. This way it will be automatically copied to the bin folder.
If you include the resources folder into the Jar, it will be available in both environments by using something like:
ImageIO.read( getClass().getResource("/image.png") )
PS: You can evade using a different resources folder but mixing the sources and images will quickly pollute your source folder.

putting picture in java program using MyEclipse GUI

I want to add a picture to my GUI program created using Eclipse and MyEclipse (for GUI visual design) from the resource pictures I pasted earlier in the project.
I managed to load pictures that lies just beside the .JAR file using
image = ImageIO.read(new File("imageFile.jpg"));
But I want to use the image from my resources "src" folder directly , so that the .JAR file is a standalone file yet loads pictures nicely.
I tried to make it
image = ImageIO.read(new File("src/ldtlogo3.jpg"));
I use this method when exporting the .JAR file
Java: export to an .jar file in eclipse
Use the overloaded ImageIO.read method taking an InputStream as a parameter, and use MyClass.class.getResourceAsStream() to get this input stream. getResourceAsStream loads a resource from the classpath (and thus from the JAR of your application). Its api doc will tell you which path it expects.
Note that the src directory is used to hold your Java source files. The jar doesn't contain it. It contains the .class files, in a hierarchy which directly maps the package hierarchy. Eclipse will automatically "compile" the image file by copying to the output directory, along with the .class files.

Categories