Can you store data inside a .jar? - java

I'm learning java and am currently trying to develop a simple application. My question is can you store data about settings, etc in a text file internal to a .jar? If so how would you go about accessing this within java? Sorry if this is a really stupid idea.

InputStream is = this.getClass().getResourceAsStream("/data/file.txt");
The resources you are getting need to be on the classpath

Yes you can, and it's not a stupid question we all need to start somewhere.
There are two parts to your question:
Adding a data/text file to a .jar - (using ant to jar it:) add "fileset dir=..." to the jar target, where dir is set equal to the directory that has the data/text file. Refer to How can I include data text files in a jar using Ant?
Accessing that data/text file from within the java code - you need to use a ClassLoader and getResourceAsStream. Refer to Loading files in JAR in Tomcat using getResourceAsStream
Also, please take a look at https://github.com/gitjonathan/turbo-sansa, I have a working version up on it.

Can you store data inside a .jar?
Read-only data can be stored inside a JAR file. You can read such data using getResourceAsStream(...) if the JAR is on the classpath, or by using the standard JAR file API class if it is not on tle classpath.
But storing update-able data in a JAR file is problematic:
In a lot of circumstances it is impossible; e.g. because the JAR file is read-only or was downloaded on the fly.
In all other cases it would be very awkward, because the standard JAR file API class does not support update in place. (You would need to create a new ZIP file, copy across the old content apart from the file you are updating, add that file, and then rename the resulting file.)

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

Extract a directory from a jar

I have a jar file that's running, but it needs an exe and a couple dlls with it to work.
To make it convenient for the user, I want to package the folder with the exe and the 2 dlls in the jar, and have it extract it when the jar is ran.
I've read answers like this one, and this one, but I still don't understand how to apply that code to what I need. I understand that a jar file is essentially a zip, but I don't know how I can get the path to the zip, and extract the folder I need from it.
I tried using the code posted here to just extract the exe for a start, but it looks like it's trying to extract the exe from the class (if that makes any sense?)
Does anyone have a code snipped they could share to show how to extract a folder with a certain name from the currently executing jar?
If you guys could help me out I would really appreciate it!
If you want to access the resources from a JAR that is on the classpath at runtime, you simply access the resources from the classpath. So no need to read it via the JAR API. Therefore your first link points to a valid solution.
It may be tricky to use the appropriate classloader. If your resource is in the same folder as a Java class file, this link may help you: How to access resources in JAR file?
URL url = getClass().getResource("path/to/img.png");
or
URL url = MyClass.class.getResource("path/to/img.png");
I think you could access the two files separately and store them to a file. There are also methods to open a stream to copy. Here is a similar question: getResourceAsStream returns null

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/

Using other documents outside a jar file

I just realised that I cant use files from outside a jar archive. If thats the case then when I deploy apps that need other documents, say an xml file, do i send the xml alongside the app or there is a way out..
Thanks
I'd suggest that you simply include the required resources within the .jar file. You can have any type of files in there, including .xml-files.
Related questions:
How do I create a jar file, which includes xml and html files?
How do I read a resource file from a Java jar file?
adding non-code resources to jar file using Ant
How to bundle images in jar file
If you really prefer to load "external" files you'll have to be more clear about the problems of opening them outside of the jar file.
But this does not work if you also want to "write" to one of those files!!! If you only want to read, put everything in there. The convention is to create a package called resources in the root of you source code ("src" for example (I use Eclipse)), and just put everything in there, and then use class.getResourceAsStream(). But if you want to write to a File, for example you want persistence for User's options or other stuff, you're gonna need to write from within the .jar, to a File outside the jar, which has a lot of permission considerations and stuff, but It's possible. use System.getProperty("java.class.path"), and you can write files just next to your jar File...

Is it possible in Java read files placed in a Jar that it's placed in a Ear too?

I was wondering if is possible to find the content in an XML file placed in a jar thath is placed in a ear too. It would help me find the properties of java beans.
Up into the ear I can iterate through documents and see what's inside, but if it is a jar I can't iterate documents inside that.
Someone can give me some advice?
From the ear file you should be able to extract the jar file. Then you can use WinZip, 7 Zip, etc to do explore the jar file contents the GUI. Or you can run the jar tf command to extract the content of the jar file in command line. If you don't have any of these tools and using windows, then you can rename the jar file to a .zip and windows should be able to explore it (most of the cases it works).
Edits - I am not sure if you wanted to do it using Java. In that case you are looking for JarFile. I found an example of it here for exploring Jar contents programatically.
so i just tested the thing you want to do - and as long as the JAR lies in the classpath of your EAR, then you can access any file within it. basically the try to look up the file from the context-root of your application.
for example if in your JAR the file abc.xml resides under the package a.b.resources, then from say a servlet in your EAR you can access it using :
InputStream is = this.getClass().getClassLoader().getResourceAsStream("a/b/resources/abc.properties");
Yes, you can read any file that is packed into zip file. It does not matter how many nested zip file you have to open on your way. Use ZipInputStream, get needed ZipEntry, read it content. If it is still zip, open it and do it again and again until you access the required resource.

Categories

Resources