How can my Java program store files inside of its .jar file?
Yes you can do this.
Non-code resources in a JAR file on the classpath can be accessed using Class.getResourceAsStream(String)
. Applications routinely do this, for example, to embed internationalized messages as resource bundles.
To get your file into the JAR file (at project build time!), just copy it into the appropriate place in the input directory tree before you run the jar
command. Build tools such as Maven, Gradle, etc can automate that for you.
Is there a way to add files to the archive within the app?
In theory, your application could store files inside its own JAR file, under certain circumstances:
- The JAR has to be a file in the local file system; i.e. not a JAR that was fetched from a remote server.
- The application has to have write access to the JAR file and its parent directory.
- The application must not need to read back the file it wrote to the JAR in the current classloader; i.e. without exiting and restarting.
- The JAR must not need to be be signed.
The procedure would be:
- Locate the JAR file and open as a ZIP archive reader.
- Create a ZIP archive writer to write a new version of JAR file.
- Write the application's files to the writer.
- Write all resources from the ZIP reader to the writer, excluding old versions of the applications files.
- Close the reader and writer.
- Rename the new version of the JAR to replace the old one.
The last step might not work if the initial JAR is locked by the JVM / OS. In that case, you need do the renaming in a wrapper script.
However, I think that most people would agree that this is a BAD IDEA. It is simpler and more robust to just write regular files.
How to list the files inside a JAR file?
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
URL jar = src.getLocation();
ZipInputStream zip = new ZipInputStream(jar.openStream());
while(true) {
ZipEntry e = zip.getNextEntry();
if (e == null)
break;
String name = e.getName();
if (name.startsWith("path/to/your/dir/")) {
/* Do something with this entry. */
...
}
}
}
else {
/* Fail... */
}
Note that in Java 7, you can create a FileSystem
from the JAR (zip) file, and then use NIO's directory walking and filtering mechanisms to search through it. This would make it easier to write code that handles JARs and "exploded" directories.
How can an app use files inside the JAR for read and write?
I need to store data into files inside .jar file and read it again
No you don't.
Instead store the 'default' file inside the Jar. If it is changed, store the altered file in another place. One common place is a sub-directory of user.home
. When checking for the file, first check the existence of an altered file on the file system, and if it does not exist, load the default file.
Note that it is generally better to describe the goal, rather than the strategy. 'Store changed file in Jar' is a strategy, whereas 'Save preferences between runs' might be the goal.
Related: What is the XY problem?
Store a file inside a jar library
Keep the file in the src/main/resources
directory and use the following method in the class where you need to load that file -
private InputStream readFileFromResourcePath(String filename) {
return getClass().getClassLoader().getResourceAsStream(filename);
}
Do not forget to close the stream after consuming it.
Reading a resource file from within jar
Rather than trying to address the resource as a File just ask the ClassLoader to return an InputStream for the resource instead via getResourceAsStream:
try (InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
// Use resource
}
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
How to Create a Jar that uses a file to save app information to
Jar files are read only, that means you can't save informations inside the jar. You can save files inside an read them but you can't edit them.
In your case there are more or less two options:
- Save the
*.json
file in e.g the OS Temp path or somewhere else where you can read and write them. - Handle like zip - https://stackoverflow.com/a/4056713/8087490 -
- Locate the JAR file and open as a ZIP archive reader.
- Create a ZIP archive writer to write a new version of JAR file.
- Write the application's files to the writer.
- Write all resources from the ZIP reader to the writer, excluding old versions of the applications files.
- Close the reader and writer.
- Rename the new version of the JAR to replace the old one.
How to write a Java program which can extract a JAR file and store its data in specified directory (location)?
Adapt this example: How to extract Java resources from JAR and zip archive
Or try this code:
Extract the Contents of ZIP/JAR Files Programmatically
Suppose
jarFile
is the jar/zip file to be extracted.destDir
is the path where it will be extracted:java.util.jar.JarFile jar = new java.util.jar.JarFile(jarFile);
java.util.Enumeration enumEntries = jar.entries();
while (enumEntries.hasMoreElements()) {
java.util.jar.JarEntry file = (java.util.jar.JarEntry) enumEntries.nextElement();
java.io.File f = new java.io.File(destDir + java.io.File.separator + file.getName());
if (file.isDirectory()) { // if its a directory, create it
f.mkdir();
continue;
}
java.io.InputStream is = jar.getInputStream(file); // get the input stream
java.io.FileOutputStream fos = new java.io.FileOutputStream(f);
while (is.available() > 0) { // write contents of 'is' to 'fos'
fos.write(is.read());
}
fos.close();
is.close();
}
jar.close();
Source: http://www.devx.com/tips/Tip/22124
How to create a file/folder from jar in Java?
getResource
will retrieve a path into the JAR file, in case the class file is also coming from there; otherwise a normal path, if not running from JAR.
Use a plain File
to get a path to a file/directory (e.g. new File("data/files/")
) that is not saved in the JAR
Related Topics
Passing Command Line Unicode Argument to Java Code
How to Change Timezone for a Java.Util.Calendar/Date
Find Place for Dedicated Application Folder
Appearance of Java Security Dialog
Spring @Autowired and @Qualifier
Is There Any Performance Reason to Declare Method Parameters Final in Java
Why Does Inputstream#Read() Return an Int and Not a Byte
Finding Largest Prime Number Out of 600851475143
Class Not Found with Ant, Ivy and Junit - Error in Build.Xml
How to Call a Method in Another Class of the Same Package
Java/Convert Iso-8601 (2010-12-16T13:33:50.513852Z) to Date Object
Please Explain About Insertable=False and Updatable=False in Reference to the JPA @Column Annotation
Explicit Type Casting Example in Java
Jsoup Character Encoding Issue
How to Enumerate Ip Addresses of All Enabled Nic Cards from Java