Images not appearing in JAR file after creating it using eclipse [duplicate] - java

This question already has answers here:
Java images not appearing in JAR file [duplicate]
(4 answers)
Closed 2 years ago.
I couldn't find an answer that works so I had to ask here. I have splashscreen file with the contents
JLabel image=new JLabel(new ImageIcon("./image/risk.jpg"));
And the folder structure looks like this
But for some reason when I go to create a jar file like this
The images don't appear in the jar file. I have looked at many other answers and they don't seem to work. I would greatly appreciate an expert eye to tell me what I am missing. Thanks in advance

new ImageIcon("./image/risk.jpg")
The images don't appear in the jar file
Non sequitur. Whether the image file is in that jar or not is irrelevant; this does not work with jar files, period.
That ImageIcon constructor takes in a file argument. File, here, is to be taken literally: It refers to a path to a file on your actual disk. You go with ., meaning: Current working directory, and thereby have lost all chances at a stable app; current working directory is whatever the JVM got started from and therefore unreliable. Even if you wave a magic wand and solve that problem, the next more pressing issue is that there is no risk.jpg file anywhere - it's an entry in a jar file, which is not, itself, a file. Merely an entry in a jar.
The solution
The solution is not to use that constructor, and instead to rely on java's resource retrieval system:
class MyClass {
public void foo() {
URL url = MyClass.class.getResource("risk.jpg");
}
}
This gets you a URL that represents a resource (could be an actual file, but could also be an entry on disk, the web, from a database, generated on the fly - whatever the classloader is providing. If you didn't mess with custom classloaders, it will always be either a file on disk, or entry in a jar file), and this can also be passed to ImageIcon (it also has a constructor that takes a URL).
This then looks for a file named risk.jpg which is sitting in the same place that MyClass.class is sitting. Whether that is on disk someplace, or in a jar file (so if this is in package com.foo;, you have a jar file with entry com/foo/MyClass.class, and that command would then find the entry com/foo/risk.jpg in the same jar file. You can use a prefix slash to go from the root of the jar: MyClass.class.getResource("/image/risk.jpg") (note, no leading dot!) will look in that jar for entry image/risk.jpg.
Great! Uh, but, that image should be in the jar, right?
Yes, this code will ensure you look in the same place class files are, which is good, but you still need to ensure the build is set up properly. 'let eclipse make a jar' is not a recommended build solution; invest some time in learning maven or gradle. However, if you insist, eclipse should just include them, but put the jpg in a source dir, right next to your java file (eclipse knows that non-java files are to be copied over, and java files are to be compiled).
In other words, if you insist on using eclipse's 'make a jar' as build tool, image has to move into src.
Alternatively, set up a basic maven project, where source is in src/main/java and image files and the like are in src/main/resources, use the maven plugin in eclipse to read the maven based project in, and that works too, if you want these directories fully separated for some reason.

Related

Storing data in text files with Java/Maven

I wrote a little Java app for analyzing .csv files. Now I want to keep reading from and writing to a .txt file, which acts similar to a mini-database. For this purpose I simply added the .txt in my project and used the Files.readString(Path) and Files.write(Path path, byte[] bytes) methods.
When I do this in IntelliJ I have no problems but as soon as I build/export the file with Maven and started with the created launcher the app didn't work because the project structure / file organization isn't the same anymore.
I also tried to just add the .txt file to the exported folder afterwards but even then I couldn't manage to implement a relative path to the file.
I'm still relatively new to programming and it's just a small app so I don't think mySQL would fit my needs. I've also read that I could store the data in a property file but I don't know if that would be the right way to archive what I want. Certainly it must be possible to somehow keep a .txt for reading and writing in your exported project. Does someone have an idea?
If you use a ´*.txt` file for storing, that file cannot be inside the jar because the jar cannot change its contents while running.
You need to put the file somewhere else, either at some dedicated location (let the user choose/configure one), or next to the jar. To figure out your own execution path, you can use
How to get the path of a running JAR file?
Maven is one tricky tool. You need to go to the pom file and add the resource.
Unable to add resources to final jar for maven project in Intellij.
-I hope this helps
Trader

Packaging an Eclipse Program With External Files

I'm not sure if this was answered previously, I tried searching for the kind of question I am asking, but I couldn't find something satisfactory. If someone could point me to a similar question, that would help.
What I am trying to do is to package an eclipse program that has external files, such as images, into a single file, rather than a jar file and the supporting files placed in the same directory.
I am not sure if that is even possible, but is there some way in eclipse that would allow you to somehow package the external files along with the jar file in a single, neat file that can be executed easily?
EDIT:
Thanks to ortis and Thorbjørn Ravn Andersen, I figured out how to do it. Here are the steps for working it out:
Firstly, ensure that all of your external files are in your src folder, not in your bin or workspace or whatever else. If you have packages in your project, they will appear as folders and the external files must be placed into those folders for use within that package.
As for calls to the external files, don't do something like this:
Image img = new Image("fileName");
Rather do this:
Image img = new Image(getClass().getResourceAsStream("fileName"));
while ensuring that "fileName" is in the src folder or package folder, if you have packages.
Some points:
-If you are initializing a global variable using a file name that is outside of your main constructor or function call, getClass(), won't work. Use:
yourClassName.class.getResourceAsStream("fileName");
-if your using JavaFX Scenebuilder and you need to package your external CSS file, here is a solution that will help you load the style sheet in your program instead of using the .fxml file to do it.
-An InputStream variable can be assigned the result of
getClass().getResourceAsStream("fileName"));
and be used instead of the whole mess.
Yes. You must reference all external files as inputstreams instead (because you want the classloader to get them from inside a jar file), and then wrap the resulting single jar file as an EXE file using http://launch4j.sourceforge.net/

Exported jar finds some files (not all) even though the paths are the same [duplicate]

This question already has answers here:
I'm trying to export a runnable jar in Eclipse, but I need it to include some other files necessary for running my program
(3 answers)
Closed 8 years ago.
When I run my program from eclipse, it shows up fine, the images from Resources\ show up, as do the sounds from the same place, and the text files are found properly. However, when I export my jar, and copy the resources into it with 7Zip, the images will work, but the sounds and the text files can't be found, even though they're in the same folder, with the same path used to find them in my code. I can fix this by putting a folder next to the jar file named Resources, and put everything in there, but I'd like to know why just putting it in the jar file only worked for the images, and how I can get it to work with the text and audio files as well.
An example to show you what I mean:
File inventory = new File("Resources/inv.txt");
threadpath = "Resources/threads.wav";
enemy1 = new Sprite(new Texture("Resources/miniForestGolem.png"));
When I run it in eclipse, all three work fine, but when I export it, and put the resources folder in the jar file, only the image works.
Edit:
I know how to include my resources, and have done so, I'm asking about how/why some of the resources aren't able to be accessed, even after adding them in.
Ok, from your comments we can infer the difference between executing it from eclipse and executing it from a .jar.
From eclipse: it works, because all that new File(...) find an actual file in Resources/
From the .jar: it won't work, since there is no file in a relative ./Resources/ path from the execution path of the application.
The way to make it work is the next:
Make sure Eclipse recognizes Resources/ as a source folder (right-click on project properties, Java Build Path, and add it as a source path)
Look for a replacement for your API methods that, instead of File objects, use InputStreams. Once you have it, retrieve all your resources as InputStreams taken from the classpath. If you are inside MyClass.java, do this: MyClass.class.getClassLoader().getResourceAsStream("Resources/inv.txt"), etc.
What you have achieved by doing this: instead of File objects built on actual operating system files, you will be retrieving InputStreams read straight from your java application classpath. This way, you can package them into a jar, or into a WEB-INF/classes directory inside a web application, or a library folder in some application servers... wherever you like as long as it is into the application classpath. I would do this if I had to package your application in a portable and usable way.

Java cannot save to a resource folder with jar

I am writing a program which is dependent on saving to a resource folder that is exported with the jar. I have a source folder titled "resources/inputs" and it exports correctly. I can load from it which is great, but the problem is, when I use:
getClass().getResource(path);
I cannot save to the path returned. I need to be able to save to it and I was wondering, is there any way I can save to this resource folder (or to some other folder existent in the same directory as the jar) no matter where the user has saved the jar file?
The error I get is a FileNotFoundException and the background I've read on it is that since jar triggers java "read-lock" you can only ever read from a jar and can never write to it? Not sure if that is accurate or not, but if it is, how can I work around this using an external folder?
I've never tried this, but its probably having a hard time because the you need to use specialized classes to access files within a jar file (which is a zip file with a different extension). Google "JarEntry" and see if that points you in the right direction.
Does this answer your question

Exporting Images with JAR in Eclipse (Java)

I've been working on a little project that requires external images for display. I'm not all that familiar with how to use Eclipse and this is my first time attempting to export a completed project so I can share it with others. Right now, it seems the only way I can get my images to show up is if I assign a specific folder on my hard drive and have the image paths in the code go to that.
I'm looking for a way to export the images as part of my JAR or as part of the same package so when I go to send this program to other people, I don't have to send them a separate archived folder of images. I'd also be interested in learning what I need to do to have my code reference the images within that package so they'll work without an external folder.
I have read about some kind of package system within Eclipse, but have thus far had no luck in figuring out how to use it. Could use some explicating!
Thanks in advance to anyone willing to give me their two cents.
Something I would have found useful with this answer is the following: make sure you put your images/files in the same eclipse folder (or sub-folder below) as your source code. I created a folder "images_ignored" using eclipse, added it to the build path but still it refused to be included in my JAR file (when creating an executable JAR).
Just drag the images folder into your Eclipse project, then choose to "Copy New Folder" or "Copy File and Folder" depending on Eclipse version, and then right click on the image folder (in Eclipse) and --> build path "use as source folder".
you might need to load them as class path resources if they are within a jar. see: getClass().getClassLoader().getResourceAsStream(...)
Use getResource() to load the images:
ImageIcon qmarkIcon = new ImageIcon(getClass().getResource("images/mark.gif"));
If you're using JDK 1.7 or JDK 1.8, you might want to use the NIO.2 API.
for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
if ("jar".equals(provider.getScheme()))
return provider.newFileSystem((new File(Start.class
.getProtectionDomain().getCodeSource().getLocation().toURI()))
.toPath(), new HashMap<String, Object>());
}
If you enter this code into a method that returns a java.nio.file.FileSystem, you can call the method to get the FileSystem for the JAR file.
To get the path to access the files inside your JAR file, you can use the following method, which then allows you to read the files however you may want.
fileSystem.getPath("/images/image.gif")
If you would like to be able to run this in Eclipse, make sure you surround the call to the method with a try/catch IOException and assign to your FileSystem object the following.
new File(Start.class.getProtectionDomain().getCodeSource().getLocation().toURI())
.toPath().toString();
This will allow you to run your program whether it's compressed into a JAR file or not.
I recommend you get used to using NIO.2, since it is a very powerful API.
If you add a folder to build path you can retrieve the images either in eclipse and when you exported it in jar file, just remember to don't reference the image with the path like img/myImage.gif but only myImage.gif !

Categories

Resources