I want to add a series of files previously extracted from other files(already done) to a jar. These files will be overwriting files inside the JAR. What is the most efficien
Extending the existing answers, I find the -C
jar option very useful when adding files that are on their own folder and you flatten their path out.
$ jar uf jar-file -C /path/to/my_jars/ this_useful.jar
You will end up having this_useful.jar right in the JAR's root:
$ jar tf jar-file | grep this_useful.jar
this_useful.jar
jar -u file.jar file1 file2 file3 ...
If someone needs a programmatically answer, here it is.
private static void createJar(File source, JarOutputStream target) {
createJar(source, source, target);
}
private static void createJar(File source, File baseDir, JarOutputStream target) {
BufferedInputStream in = null;
try {
if (!source.exists()) {
throw new IOException("Source directory is empty");
}
if (source.isDirectory()) {
// For Jar entries, all path separates should be '/'(OS independent)
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty()) {
if (!name.endsWith("/")) {
name += "/";
}
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles()) {
createJar(nestedFile, baseDir, target);
}
return;
}
String entryName = baseDir.toPath().relativize(source.toPath()).toFile().getPath().replace("\\", "/");
JarEntry entry = new JarEntry(entryName);
entry.setTime(source.lastModified());
target.putNextEntry(entry); in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true) {
int count = in .read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
} catch (Exception ignored) {
} finally {
if ( in != null) {
try { in .close();
} catch (Exception ignored) {
throw new RuntimeException(ignored);
}
}
}
}
A JAR file is a ZIP file, remember.
Just use some ZIP library.
String cmd = "jar uvf " + "jarName" + " " + "Filename";
System.out.println(cmd);
try {
Process p = Runtime.getRuntime().exec(cmd);
}
catch (Exception ex) {
}
Just to add to the existing answers, there is at least one special case: so-called executable JAR files. If you add another JAR file as a dependency -- whether you use jar or zip -- it will complain that the embedded file is compressed:
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/file.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
The solution to this is to use the 0
option to jar:
jar uvf0 myfile.jar BOOT-INF/lib/file.jar
You don't need this for normal class files.