Can't load resources when running the code from an executable JAR - java

I'm having this problem where none of the resources load when I run a JAR of the program. I've changed code and checked that it is indeed both the code that loads images and the code that loads sounds do not work. It works perfectly fine when I run it in eclipse. I checked with 7-Zip and the sounds and images files aren't in a res folder anymore. I tried changing the path files and the location of the resources in my program before I exported it, but that didn't work. I also have the res folder as a source folder in the build path. I'm exporting the JAR with eclipse, and then adding my libraries into it with JarSplicer. Here are the codes that load images and sound resources:
-Load Sound-
public static WaveData LoadSound(String path){
WaveData sound = null;
try {
sound = WaveData.create(new BufferedInputStream(new FileInputStream(path)));
} catch (Exception e) {
e.printStackTrace();
}
return sound;
}
-Load Images-
public static Texture LoadTexture(String path, String fileType){
Texture tex = null;
InputStream in = ResourceLoader.getResourceAsStream(path);
try{
tex = TextureLoader.getTexture(fileType,in);
}catch(IOException e){
e.printStackTrace();
}
return tex;
}
Here's my error in the command prompt:
Here are the files in the jar every time I exported it (regardless of whether the resources were in res or not):
I'm stumped here. If someone knows how to fix this, then please help me out.

I found the answer to my problem.
ResourseLoader.getResourceStreamAs() does not work inside of JAR files, so you need to do getClass().getResourceStreamAs(), or [ClassName].class.getResourceStreamAs(), if it's static.
Also, I had to change the location of the files from res/[resource file]/[resource] to /[resource file]/[resource] because when you export, it takes out all of the files in res. Also, you have to make sure that you have that / at the beginning of the path there in order to designate it to search in the source folder, or else it will search in the folder of the class that called getResourceStreamAs(). And also, new FileInputStream() doesn't work in JAR files, so you have to use [ClassName].class.getResourceStreamAs() instead. Oh, and on top of that, I had a few files that somehow got the extension part its name in all capitals for no reason. So that gave me some confusion. I basically just had to do a bunch of fiddling with code, but I got it working!
One more thing: make sure you add your resources folder to the sources tab in the build path, or else eclipse won't export it. And if you want your libraries to be exported in your JAR, then you'll have to add them manually by making a fat jar with JarSplicer.

Turns out that paths to resources are case sensitive and do not work in jar files if there is a single misstyped letter in the path.

Related

How to access images within a .Jar File

I've been trying for a couple of days to access an image within a .Jar file. I've taken a look at several solutions on this site and nothing seems to be working for me. I've tried several instances of the code included below, using URL and inputStreams, with full path names, reduced path names, and automating the path names using system.getProperty("user.dir"); I've tried alternating between forward and backslashes, doubling up on backslashes and the like.
I also understand that accessing an image in a .jar is not the same as locating a file and it's path.
Code I've tried using:
url = getClass().getResource("/ball.PNG");
try {
image = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
try {
image = ImageIO.read(this.getClass().getResource("/ball.PNG"));
if (image == null){
System.out.println("Could not find image for the ball!");
}
catch (IOException e) {
e.printStackTrace();
}
InputStream input = getClass().getResourceAsStream("ball.PNG");
try{
image = ImageIO.read(input);
}
catch(IOException e){
e.printStackTrace();
}
None of these solutions are working. compiling and running works just fine. The jar file is made just fine, and when I look inside, the PNG I used is included. Actually running the .Jar file gives me the error "Exception in thread "main" java.lang.IllegalArgumentException: input == null!" along with a few more lines that just indicate that errors occur when trying to pull information from the image.
The most interesting part to me is that most of these solutions work in some form or another when running the .class files, but none work for the .jar file.
For more context, the variable image is a BufferedImage; I've been using Notepad++ and command prompt to run, compile and create the .class and .Jar without issues. There is no subdirectory for the image files, and again after checking, they are included in the .jar file. I have no idea why the .class files can find the images and use them but the .jar files cannot.
I know the code isn't pretty to look at and a bit incomplete, but keep in mind that these are just quick examples I've written up. Compiling and running works just fine, as does running the jar files. Only the .jar file has trouble locating the image file. I've looked at these threads and used their examples to form my code:
Using png in a jar file
Access .png image in .jar file and use it
Some edits others have asked for:
A picture of the files and their location
A picture of the command "jar tf BallGame.jar"
posted in a code block:
C:\Users\Phili\Documents\TheBallGame>jar tf BallGame.jar
META-INF/
META-INF/MANIFEST.MF
Ball.class
BallGame$1$1.class
BallGame$1$2.class
BallGame$1.class
BallGame.class
Coin.class
gamePanel.class
GlobalConstants.class
RedBall.class
ball.png
coin.png
Distances and stuff.png
redBall.png
A picture of what is actually inside the jar file.

How to create a runnable jar that uses files and images as

I want to understand the best or the standard technique to write a java project when using internal files. To be precise, I want to develop a project that uses text files and images that are needed when the program runs. My goal is to create a runnable jar from the project in which the user does not need to see all these files. Therefore, I decided to create a package called resources and put it inside the folder that contains the source codes. I.e. it is in the same level as other packages. Now, in my codes when I want to use the images I use the following statement:
URL url = getClass().getResource("/resources/image1.gif");
It is working!
Then, to open a text file for reading/writing, I use the following:
String filename= "/resources/"+file1.txt;
Now, this is not working and it complains that it cannot find the file. I am not sure how to go about this?
A google search suggested that I put the resources folder on the project root directory. It is working then but when I created the runnable jar I had to put the resources folder on the same directory as the jar. This means that the user can have access to all the files in there. Any help is much appreciated.
You can use the getResource method for files too.
URL url = getClass().getResource("/resources/file1.txt");
try {
File f = new File(fileUrl.toURI());
} catch (URISyntaxException e) {
//dealing with the exception
}

In netbeans, how to save or access an image after deploying jar file

I am trying to make a mess management application in Java using NetBeans. I want to save images of Members in a specified folder inside my src directory. I just created folder named EmpImgs for storing employees images. Here is my code:
File srcDir = new File(file); // current path of image
File dstDir = new File("src\\J_Mess_Mgnt\\EmpImgs\\"+Txt_C_G_M_M_ID.getText());
objm.copyFile(srcDir, dstDir);` // copy image from srcDir to dstDir
Here I use another class for copying images to predefined folders and renaming the images based on their ID.
Everything is working properly in Java IDE.
But unfortunately after making an executable .jar file, this code will not work. I cannot save or access any image file in that directory.
I just went through this site, but I didn't find a suitable answer.
All I need is saving and editing images inside jar folder
Hehe hi mate you need some help. This is a duplicate but I will cut you some slack and maybe you should delete this later. So back to basics, the jvm runs byte code, which you get from compiling java source code to .class files. Now this is different to C and C++ were you just get a .exe. You don't want to give your users a bunch of .class files in all these folders which they can edit and must run a command on the command line, but instead give them what is known as an 'archive' which is just an imutable file structure so they can't screw up the application, known as a jar in java. They can just double click on the archive (which is a jar), and the jvm will call the main method specified in the MetaInf directory (just some information about the jar, same as a manifest in other programming languages).
Now remember your application is now a jar! It is immutable! for the resasons I explained. You can't save anymore data there! Your program will still work on the command line and in IDEs because it is working as if you used your application is distrubuted as bunch of folders with the .class files, and you can write to this location.
If you want to package resources with your application you need to use streams (google it). BUT REMEMBER! you cant then save more resources into the jar! You need to write somewhere else! Maybe use a user.home directory! or a location specified from the class path and the photos will be right next to the jar! Sometimes you might need an installer for your java application, but usually you don't want to create the extra work if you don't need to.
At last I find an answer suit for my question.It is not possible to copy images or files to a executive jar folder.So I used a different Idea.Create some folders(as per our requirement),Where my executable jar folder is located(No matter which drive or where the location is).The code is..
String PRJT_PATH=""; //variable to store path of working directory.
private void getdire() throws IOException{
File f=new File(".");
File[] f1=f.listFiles();
PRJT_PATH=f.getCanonicalPath(); //get path details.for eg:-E:/java/dist
}
private void new_Doc_folder(){ //function for creating new folders
try{
String strManyDirectories="Docs"+File.separator+"Bil_Img"; //i need to create 2 folders,1st a folder namedDocs and In Docs folder another folder named Bil_Img
String SubDirectories="Docs"+File.separator+"EmpImgs"; //same as above but keep in mind that It will not create a Same folder again if already exists,
// Create one directory
boolean success = (new File(strManyDirectories)).mkdirs(); //create more than one directory
boolean success1 = (new File(SubDirectories)).mkdir(); //Creates a single directory
if (success && success1) {
}
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
It works Successfully.
Regds

Proper path for using ClassLoader.getResource()?

I've made a function(Java) that is supposed to read bytes from a file and print them to the console:
public void loadPixels(int size){
ClassLoader cl = this.getClass().getClassLoader();
pixels = new byte[size];
try{
InputStream stream = cl.getResource("res/" + fileName).openStream();
stream.read(pixels);
System.out.println(pixels.toString());
stream.close();
}catch(Exception e){
e.printStackTrace();
}
}
The problem is, I'm getting a NullPointerException on the line
InputStream stream = cl.getResource("res/" + fileName).openStream();
For the file I'm trying to open, the name is "font.spt", which is also the value held by fileName. This file is within the folder "res" in the project's root directory, and I'm currently using the Eclipse IDE.
Is my approach to the path for the file wrong, or is something else the issue?
To recap: fileName points to "font.spt", which is under the "res" folder in the bin directory.
EDIT: the "res" folder containing the .spt file is now under the "bin" for the project, rather than the root directory, but I still get the error. When running from the IDE or as an exported .jar, I still get the NullPointerException, where am I supposed to put these files? Can someone give me a screenshot or example?
By default, Eclipse will copy all non .java files it finds in the project's Source Locations to the Output Folder when it builds. So one option is to just place your resource files under the source folder along with your source code. However, a better option is to use a separate resources folder for non-Java files and declare that as an additional Source Location (via your project's Java Build Path properties). That's how Maven and Gradle projects are organized, too.
For example, you might have:
MyProject\
src\
java\
com\
....*.java
resources\
fonts\
font.spt
With both src\java\ and src\resources\ defined as Source Locations in the Build Path. Then your code to load the file would be like:
getResource("fonts/" + fileName)
Something to consider: use Gradle or Maven to manage your builds, both of which enforce/provide a project structure similar to this anyway.

Where to put a textfile I want to use in eclipse?

I need to read a text file when I start my program. I'm using eclipse and started a new java project. In my project folder I got the "src" folder and the standard "JRE System Library" + staedteliste.txt... I just don't know where to put the text file. I literally tried every folder I could think off....I cannot use a "hard coded" path because the text file needs to be included with my app...
I use the following code to read the file, but I get this error:
Error:java.io.FileNotFoundException:staedteliste.txt(No such file or directory)
public class Test {
ArrayList<String[]> values;
public static void main(String[] args) {
// TODO Auto-generated method stub
URL url = Test.class.getClassLoader().getResource("src/mjb/staedteliste.txt");
System.out.println(url.getPath()); // I get a nullpointerexception here!
loadList();
}
public static void loadList() {
BufferedReader reader;
String zeile = null;
try {
reader = new BufferedReader(new FileReader("src/mjb/staedteliste.txt"));
zeile = reader.readLine();
ArrayList<String[]> values = new ArrayList<String[]>();
while (zeile != null) {
values.add(zeile.split(";"));
zeile = reader.readLine();
}
System.out.println(values.size());
System.out.println(zeile);
} catch (IOException e) {
System.err.println("Error :"+e);
}
}
}
Ask first yourself: Is your file an internal component of your application?
(That usually implies that it's packed inside your JAR, or WAR if it is a web-app; typically, it's some configuration file or static resource, read-only).
If the answer is yes, you don't want to specify an absolute path for the file. But you neither want to access it with a relative path (as your example), because Java assumes that path is relative to the "current directory". Usually the preferred way for this scenario is to load it relatively from the classpath.
Java provides you the classLoader.getResource() method for doing this. And Eclipse (in the normal setup) assumes src/ is to be in the root of your classpath, so that, after compiling, it copies everything to your output directory ( bin/ ), the java files in compiled form ( .class ), the rest as is.
So, for example, if you place your file in src/Files/myfile.txt, it will be copied at compile time to bin/Files/myfile.txt ; and, at runtime, bin/ will be in (the root of) your classpath. So, by calling getResource("/Files/myfile.txt") (in some of its variants) you will be able to read it.
Edited: Further, if your file is conceptually tied to a java class (eg, some com.example.MyClass has a MyClass.cfg associated configuration file), you can use the getResource() method from the class and use a (resource) relative path: MyClass.getResource("MyClass.cfg"). The file then will be searched in the classpath, but with the class package pre-appended. So that, in this scenario, you'll typically place your MyClass.cfg and MyClass.java files in the same directory.
One path to take is to
Add the file you're working with to the classpath
Use the resource loader to locate the file:
URL url = Test.class.getClassLoader().getResource("myfile.txt");
System.out.println(url.getPath());
...
Open it
Suppose you have a project called "TestProject" on Eclipse and your workspace folder is located at E:/eclipse/workspace. When you build an Eclipse project, your classpath is then e:/eclipse/workspace/TestProject. When you try to read "staedteliste.txt", you're trying to access the file at e:/eclipse/workspace/TestProject/staedteliste.txt.
If you want to have a separate folder for your project, then create the Files folder under TestProject and then access the file with (the relative path) /Files/staedteliste.txt. If you put the file under the src folder, then you have to access it using /src/staedteliste.txt. A Files folder inside the src folder would be /src/Files/staedteliste.txt
Instead of using the the relative path you can use the absolute one by adding e:/eclipse/workspace/ at the beginning, but using the relative path is better because you can move the project without worrying about refactoring as long as the project folder structure is the same.
Just create a folder Files under src and put your file there.
This will look like src/Files/myFile.txt
Note:
In your code you need to specify like this Files/myFile.txt
e.g.
getResource("Files/myFile.txt");
So when you build your project and run the .jar file this should be able to work.
Depending on your Java class package name, you're probably 4 or 5 levels down the directory structure.
If your Java class package is, for example, com.stackoverflow.project, then your class is located at src/com/stackoverflow/project.
You can either move up the directory structure with multiple ../, or you can move the text file to the same package as your class. It would be easier to move the text file.
MJB
Please try this
In eclipse "Right click" on the text file u wanna use,
see and copy the complete path stored in HDD like (if in UNIX "/home/sjaisawal/Space-11.4-template/provisioning/devenv/Test/src/testpath/testfile.txt")
put this complete path and try.
if it works then class-path issue else GOK :)
If this is a simple project, you should be able to drag the txt file right into the project folder. Specifically, the "project folder" would be the highest level folder. I tried to do this (for a homework project that I'm doing) by putting the txt file in the src folder, but that didn't work. But finally I figured out to put it in the project file.
A good tutorial for this is http://www.vogella.com/articles/JavaIO/article.html. I used this as an intro to i/o and it helped.
Take a look at this video
All what you have to do is to select your file (assuming it's same simple form of txt file), then drag it to the project in Eclipse and then drop it there. Choose Copy instead of Link as it's more flexible. That's it - I just tried that.
You should probably take a look at the various flavours of getResource in the ClassLoader class: https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html.

Categories

Resources