I know this question has been asked a bunch of times before, but I'm peeled through all the other threads and tried a bunch of stuff, but can't find anything that resolves my issue. I have a program that compiles and runs without issue in Eclipse, but when I export a runnable .jar file, it won't launch. I tried running it from the cmd prompt, and got the error Illegal Argument Exception: URI in not hierarchical. This is happening in an included sound file which I have as a classpath resource. The code is like this:
try {
pop = new File(IntroView.class.getResource("/model/pop.wav")
.toURI());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
From what I've read it's a problem with the way that the file is being packed up into the .jar, but I'm having a hard time wrapping my head around it. Can anybody shed some light on this and possibly provide a solution? Thanks.
I am sorry but it seems you cannot represent a File object from inside a JAR. When locating a file using File object it checks for file in the OS directory structure only. The File object can locate the JAR itself in a directory but not what's inside.
You can get the InputStream to the file inside JAR like this as stated in a few places:
InputStream input = PlaySound.class.getResourceAsStream("Kalimba.mp3");
You could have these options:
Read the file from JAR and write it outside in your directory and
then get the File Object.
Extract the JAR to a folder and point to that with a File.
Simply get the InputStream and play the file as shown here:
How can I play sound in Java?
Alright so I got it working, but it's not really an ideal solution. What I ended up doing is creating a folder within the project, but outside of the source. So before, the resources were in
Project/src/Model/pop.wav
Now they are in
Project/Resources/pop.wav
I then just accessed then like this
pop = new File("Resources/pop.wav");
So as this stands, it still only works when launching from the IDE, but what I did was add a new folder within the same folder that the .jar is being run from which contained all the same resource files. The file reference looks for pop.wav relative to whichever directory the program(either in the IDE of from the .jar) is being run from, so it finds the files in this new folder and works fine. I don't feel it's the prettiest solution, but it works anyway.
Related
I have tried many variants but I cant find correct.
I have something like
Inside my jar, which created by Maven I can see that
That is my folder with classes. And, by the way, If I start my program in IDEA, not from Console, there is not any exception with paths
Here, I am in debug mode start my jar trying to see, where is the problem.
If I do 'file.exists()' it would be false but file inside. I think, that problem because of '.jar!\' in the path, but I don`t know how to remove that.
Anyway I've tried absolute and relative path, I've tried
Thread.getCurrentThread.getContextLoader.getResource()
GUI.class.getResource()
GUI.class.getClassLoader.getResource()
Nothing help
You can't use File to open resources inside a jar file. File can only be used with normal files and directories.
Note: using File works fine within in the IDE, since all files are not packaged in a jar file yet. But the program will break after you package it.
Once you locate the resource eg. URL res = GUI.class.getResource("/rxtx64/myres.dll") , you can open that resource as a stream InputStream is = res.openStream(); .
See also related answers Utils to read resource text file to String (Java) and How to read a text-file resource into Java unit test?
Sitting here with a bigger java project (for a first year software student) having some troubles creating the correct file path to resources.
I right now have files in the form of .txt, .png, .jpg, and a .gif.
Right now i use paths like this to find a text file:
File userFile = new File("Source Code/files/users.txt");
Or paths like this to create an image loaded in my FX code:
File logoPath = new File("Source code/files/graphics/Streamy_logo.png");
Image logoImage = new Image(logoPath.toURI().toString());
logo.setImage(logoImage);
This works fine in my IDE (IntelliJ), however it doesn't work when i create the project as a Jar file.
I think is has to do with the "source code" directory not created in the jar-file, which makes sense now.
Tried to read different subjects, but it seems a bit different if i should use a getResources-method, set a resourceStream or something else.
Can anybody please help me with this.
Thank you!
You can't load files like that in .jar files here's an example on how to read BufferedImages.
But first, make sure you have marked the resource folder as a resource folder in IntelliJ by right-clicking the folder in the project view and going down to "Mark directory as" and checking resource root.
BufferedImage exampleBlock = null;
try {
exampleBlock = ImageIO.read(ClassLoader.getSystemResource("exampleBlock.png"));
} catch (IOException e) {
e.printStackTrace();
}
By using this method of getting files all your files will be implemented into the .jar file and you can use them by calling their file name + extension
For maven or gradle projects, that respects maven directories convention you can simply use
getClass().getResource("/your_file_located_in_src_main_resources.extension").getPath()
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.
This question already has answers here:
Reading a resource file from within jar
(15 answers)
Closed 6 years ago.
I built a game a while ago in eclipse. I wanted to export it like usual to a .jar. I've done this before and with my other projects it works. This one doesn't work because it gives a blank white screen. I put in a System.exit(1) on a different spots to see where the program stops working. Eventually I found the spot. It can't seem to locate my .txt file but in eclipse if does work. I've checked the .jar with 7zip(like winzip) and the .txt file is in there. I also used the command line to open it and it gives the same error of not being able to locate the .txt file. I've looked a lot on the internet and stackflow for people that have same questions of related problems but they didn't offer a fix unfortunately.
The code that make a new world is this.
world = new World(handler,"res/worlds/world1.txt");
In the world it calls this funtion:
loadWorld(path);
This funtion should return back a string. First it calls another function to get that string:
String file = Utils.loadFileAsString(path);
Finally this is the code that doesn't work because the file can't be located.
public static String loadFileAsString(String path){
StringBuilder builder = new StringBuilder();
try{
BufferedReader br = new BufferedReader(new FileReader(path));
String line;
while((line = br.readLine()) != null)
builder.append(line + "\n");
br.close();
}catch(IOException e){
e.printStackTrace();
}
return builder.toString();
}
Is there something that I missed? Eclipse runs it fine but after exporting its like the .txt isn't exported but it is still there.
Thanks in advance.
The java class File (which is used by FileReader) operates on OS the file system path, either absolute, or relative to the current working directory. Your example denotes a relative path. I beg "res/world/..." is just beyond your project folder in eclipse. When running an app in eclipse the current directory is the project path itself. Therefore your code worked in eclipse.
Running standalone (by starting a jar) the file cannot be found in the same OS path. It is located within the jar. Therefore you must access it by using the resource loading features of your classloader.
That is a relative path. Relative paths are resolved relative to where you are when you execute the application. In eclipse this is, by default, the project directory. However, if you are running the jar externally, it will depend entirely on how you run the jar.
One common solution is to always have the jar placed in the same location relative to the resource (world1.txt). For example, the following directory structure...
-lib
--main.jar
-res
--worlds
---world1.txt
main.sh
Then, you need to get some base directory into your application. One way is to pass in the absolute path to main.jar as a command line argument, system property, or environment variable.
Another common approach is to get the path of the running jar file using some technique like this.
Finally, in your application, instead of using a relative path, you can use an absolute path:
String world1Path = baseDirectory + "res/worlds/world1.txt"
If you have an archive reader (such as 7zip) open up the .jar and see if your .txt file is inside the .jar. If not, simply copy the .txt file into the .jar file. This happened to me when trying to use a .png for a Java application. Hope it works out!
I have completed a program in eclipse and now I would like to export it as a single runnable jar file. The program contains a resource folder with images and text files in it. This is located beneath the source folder.
The res file is not added to the build path however when I run the program in Eclipse it still works.
The thing that is confusing me is that the res file is being saved into the runnable jar file when I export it as I can open the Jar file with WinRar and I see the folder is there with all the objects in it. But when I run the problem it stops at the point that the resource folder is referenced. To add to my confusion when I manually copy and paste the res folder next to where the runnable jar file is saved and run the program it works exactly as it should do.
Now I know this is something to do with how I reference the files in my code. At the moment I have it like this
reader = new LineNumberReader(new FileReader("res/usernames.txt"));
This works exactly how I want and accesses the res folder without any exceptions - in Eclipse and when I move the resource folder next to the Jar file.
I would like it to work normally but without having a folder outside of the Jar file I would like it all encapsulated in one Jar file.
I did a lot of research and what seems to be a common fix - may I add I don't really know how it works but everyone seems to mention it - is to somewhere use:
myClass().getResource()
When I create a new FileReader it needs a String input however when I use myClass().getResource() it returns a resource and not a string. I also don't have a clue how it is meant to reference the resource folder. Should I move the resource folder into the source folder?
Does anyone know how I can reference the resource folder from within the runnable jar file?
Sorry for rambling question I know what I want for my final product but I'm getting confused by the build paths and referencing from within classes and I have searched online for a long time trying to figure it out.
Resources, when you deploy your software, are not deployed as files in a folder. They are packaged as part of the jar of your application. And you access them by retrieving them from inside the jar. The class loader knows how to retrieve stuff from the jar, and therefore you use your class's class loader to get the information.
This means you cannot use things like FileReader on them, or anything else that expects a file. The resources are not files anymore. They are bundles of bytes sitting inside the jar which only the class loader knows how to retrieve.
If the resources are things like images etc., that can be used by java classes that know how to access resource URLs (that is, get the data from the jar when they are given its location in the jar), you can use the ClassLoader.getResource(String) method to get the URL and pass it to the class that handles them.
If you have anything you want to do directly with the data in the resource, which you would usually do by reading it from a file, you can instead use the method ClassLoader.getResourceAsStream(String).
This method returns an InputStream, which you can use like any other InputStream - apply a Reader to it or something like that.
So you can change your code to something like:
InputStream is = myClass().getResourceAsStream("res/usernames.txt");
reader = new LineNumberReader( new InputStreamReader(is) );
Note that I used the getResourceAsStream() method from Class rather than ClassLoader. There is a little difference in the way the two versions look for the resource inside the jar. Please read the relevant documentation for Class and ClassLoader.