(Java) Trouble going between URLs and files with a .jar file - java

I'm making a rather big program in java. It has lots of files, including images, audio, and text files. When I'm running from Eclipse, the code I use works fine. However, I always have trouble gaining access to them from a .jar file that's on its own.
I'll give you an example of how I'm coding this.
For the BufferedImage, I have it this way:
File bgImgFile = new File("images/nature.jpg");
BufferedImage bgImg = ImageIO.read(bgImgFile);
For the AudioInputStream, I have:
File soundFile = new File("audio/two.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
And for the text file, I have:
FileReader reader = new FileReader("scripts/0.txt");
This all works fine for when I'm in Eclipse. However, I'm thinking about what I'll want to do for distribution. I want to have a .jar file that can run anywhere, and doesn't need to be in the same directory as those folders containing the files. I've done this before and it's worked fine.
This is what I tried to do for the image:
URL bgFileUrl = MainClass.class.getClassLoader().getResource("images/nature.jpg");
File bgImgFile = new File(bgFileUrl.getFile());
BufferedImage bgImg = ImageIO.read(bgImgFile);
I did similar things for the audio and text file. However, even when I tried in different combinations of having the files themselves in the same directory, having a slash in front of the plain file name, etc., nothing worked. I want to be able to include these files in the .jar file so I don't have to run the .jar from that specific folder.
One thing I don't understand is that, when I opened up the .jar file made using my original code, the images, audio, and scripts folders were in there and they had my files. They were there. However, when I tried to run it, I got an IIOException ("Can't read input file!") and a NullPointerException, even though I was using the same code as before.
How do I make it so the files are included in the .jar file so it can run on its own?
Thanks for the help!

Can you try below code
URL audioFileUrl = MainClass.class.getClassLoader().getResource("audio/two.wav"");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(audioFileUrl);

Related

Writing Information (and Image) to a Jar File from another Java Program

Possibly a duplicate, though I doubt so since I have not seen anything so far completely answering my criteria in a way that I can complete my program
Background
What I need is to access another jar, from a seperate jar, read and write files to that jar. So far what I have done is change the jar to a zip and then I can delete files, but the problem I am having is with writing files back in, specifically image files (.txt works perfectly fine)
Question
How do I write image files to a zip (that was originally a jar) from another java program (in the end product another jar)
Note
I have looked around and most sources say this is not possible, but those questions dealt with this during the running of a program, my special case is that the other program is not running, but in file format. All I want to do is write and image in and convert it back to a jar and not have any problems with running that jar in the end.
Thank you!
Use FileSystems to access, write and replace the contents of the jar file:
try (FileSystem fs = FileSystems.newFileSystem(Paths.get("path/file.jar"), null)) {
Files.copy(Paths.get("path/to/image"), // path to an external image
fs.getPath("image.jpg"), // path inside a jar file
StandardCopyOption.REPLACE_EXISTING);
}

Generated .jar is unable to load some media files

I built a java program using IntelliJ. This program loads media files like an image (.jpg) and audio (.wav).
When i run my project inside of the IDE, it works fine.
But when i generate a .jar file of my project, the image and audio files will not load.
When i try to load the .wav audio file, i get a FileNotFoundException
When i try to load the .jpg file, i get an IIOException: Can't read the input file!
I'm loading the image like this:
image = ImageIO.read(ImageScreen.class.getResourceAsStream("/quiz/resources/images/image_1.jpg"));`
When i inspect the top of the stack trace in the debugger, i can see: javax.imageio.ImageIO.read(Unkown Source).
In other parts of my application, i'm able to load text files from a similar directory like this and it works in the .jar file too:
reader = new BufferedReader(
new InputStreamReader(
WordScreen.class.getResourceAsStream(
"/quiz/resources/words/wordlist.txt")));`
I only have one package called quiz in my project and i don't understand why this isn't working, as i am specifying an absolute path.
I've looked at other questions such as this one, but in my opinion, i'm doing what is being suggested.
Thank you everyone for your help. I have managed to find a fix for my problem.
I have changed this:
image = ImageIO.read(ImageScreen.class.getResourceAsStream("/quiz/resources/images/image_1.jpg"));
To this:
image = ImageIO.read(this.getClass().getResourceAsStream("/quiz/resources/images/image_1.jpg"));
I am now retrieving the .wav in the same way and it is working:
this.getClass().getResourceAsStream("/quiz/resources/audio/audio1.wav");
try with getClassLoader()
this.getClass().getClassLoader().getResourceAsStream...

Cannot Construct An Image Object With Relative File Path WIthout Using file: Prefix

I have been trying to create an image object like this:
Image img = new Image("images/jack.png");
or
Image img = new Image("jack.png");
or /jack.png or /images/jack.pngetc.
I have looked up the working directory using System.getProperty("user.dir") and it is indeed where I put my image file. When I use file: prefix, it does work, like so:
Image img = new Image("file:images/jack.png");
However, it is also supposed to work without using it. In the textbook it is done without file:. I've seen other codes that work without it.
At the end of a bunch of chained exceptions, it says:
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
I also tried to read source code from OpenJDK and I could figure anything out because many methods were native and from what I traced I didn't understand how it didn't work. Also, I can create files the same way, I just can't create images. For instance, this works:
File file = new File("fileName.txt");
What causes this problem, what should I do to fix it?
I'm using NetBeans, if that matters.
Note that System.getProperty("user.dir") does not return the working directory. It returns the user directory.
A path relative to the working directory can be specified using a relative file path in the File constructor. However it's bad practice to rely on the working directory. Starting the application from NetBeans results in the working directory being the project directory, but this is not the case, If started in a different way.
Images you need in your application should therefore be added to the jar.
In this case you can retrieve the image URL via Class.getResource(). (convert to String using toExternalForm().)
If you have a File that references a image file, you can use the File instance to get a URL:
File file = ...
String urlString = file.toURI().toURL().toExternalForm();
Those URLs can be used with the Image constructor.
Note that
File file = new File("fileName.txt");
does not create a file. It just represents a file path. This file may or may not exist. Simply invoking the File constructor does not create a new one.
File file = new File("name.txt");
creates a file somewhere. It doesn't read the existing file whereas
Image image = new Image("pathToImage.png");
tries to read the existing image. In order to be able to read an image stored somewhere you need either the absolute path, which requires the protocol (http, file, ftp etc.) or you put your image into the 'known' directory, like the resources dir of your project.
Say, you have your java sources under src/main/java. The resources dir could be src/main/resources. Put your image there and try working with relative path relative to src/main/resources.

Java: Reading in an image from same folder as java files

I have code that reads in an image file from the same directory as the java files, but currently I can only get it to work if the entier path is given.
picture = new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\...\\ogre.png"))));
The image is in the same folder as the java files. But when I try just "ogre.png" or ".\\ogre.png" or similar it does not work.
My question is this:
I will be exporting to a JAR eventually, will this affect that once the jar is created? (I'm assuming yes, since creating a jar doesnt change the source code).
How can I read the file from the same folder instead of the exact file path, In a situation where the containing folder were to be moved for example.
This is the standard way... (and it will work when everything is in the jar)
URL url = OneOfYourClass.class.getResource("package/pathTo/image/ogre.png");
ImageIcon image = new ImageIcon(url);
OneOfYourClass is a class that you have (maybe the main class)
package/pathTo/image/ is the path from this class to find your image

Images are not displaying in jar but displaying in compiler?

I know, I know, this has been asked before. But every resource I've looked at uses IconImages while I just have plain Images.
Is there a different solution? Please help as I've been stuck researching and trying to figure this out for days now with no progress.
Image Floor = Toolkit.getDefaultToolkit().getImage("Floor.PNG");
EDIT: If I was to make sure the jar wouldn't compress and I created a seperate directory in the jar for images and put the correct file path, would this code work?
Toolkit#getImage(String s) looks for a file and likely your image is in the Jar and is now a resource not a file. Look to using resources for this.
Note that ImageIO.read(...) can accept an InputStream parameter the Class class has a method, getResourceAsStream(...) which can put the resource into a Stream that ImageIO can read. Give that a try.
Also, are you getting any error messages when you try what you're doing?
Make sure you know what your current directory is, and how it relates to the position of the files in your jar.
Here's how I would handle it.
1) Require there to be a file called "images.txt" in the directory with your jar (or bundle it into the jar.)
2) Make a file called "images.txt" with a format like `FLOOR:C:\\images\\floor.png`
3) Load this file into memory on load.
4) Load your images based on the entries in the file
This will give you the advantage of changing your images without changing your code if it's defined outside the jar :)
It's not loading because you're not putting the path to the images in the declaration. It expects the images to be wherever the jar is (notice there's no directories there)
You need to offload the definition of the file names to a file, or at the very least guarantee the relative position of the files.
Another good option is to put the images in the jar itself, say in an img directory, and reference them there. But then changes to the images require a new jar, which may not be desired for development purposes.
The getImage call is looking in the file system working directory, not inside the Jar file. This is why the jar file loads the images successfully when they are placed in the same directory outside the jar file. If the images are bundled in the jar file, they are no longer file system files to be accessed, but rather Jar file resources. There is a different way to load these, but sorry, I don't know it off the top of my head.
Check the extension of files. I had this problem because the extension was "PNG", when I changed it to "png", everything was ok.
You can't expect a JAR file to magically know where your images are. If you put a JAR file alone on the desktop, it's going to look for the files on the desktop! The code
getImage("Floor.png")
searches the current directory of the JAR (or source project) by default and you'd expect that if the JAR was in the same directory, it would work. If the JAR is on the desktop how does it know where Floor.png is? Of course, you can specify a hard-coded path
getImage("C:\Some Folder Path\Floor.png")
but then Floor.png has to be in C:\Some Folder Path\ for the JAR to work properly.
It sounds like what you really want to do is keep the images in the JAR file (which acts like a ZIP file). The tutorial on doing that is here:
http://download.oracle.com/javase/tutorial/uiswing/components/icon.html#getresource
And I know for ImageIcon you use: new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg") but I have not found anything similar for plain Image.
<head-desk /> You should really get into reading the JavaDocs. Otherwise you are 'coding by magic'. Which generally won't work.
URL urlToImage = getClass().getResource("myimage.jpeg");
// If you need to support Java 1.3
Image image = Toolkit.getDefaultToolKit().getImage(urlToImage);
// If your users have dragged their JRE into this millennium
BufferedImage bufferedImage = ImageIO.read(urlToImage);

Categories

Resources