How does one create a JAR file programmatically using java.util.jar.JarOutputStream
? The JAR file produced by my program looks correct (it extracts fine) but when I try loading a library from it Java complains that it cannot find files which are clearly stored inside it. If I extract the JAR file and use Sun's jar
command-line tool to re-compress it the resulting library works fine. In short, something is wrong with my JAR file.
Please explain how to create a JAR file programmatically, complete with a manifest file.
First create your java file as you require. Right click your project -> click on export -> select option jar, follow the dialog box. Now, you have created your own java jar file. Create your new project as you require, import that jar file as you are importing other jar files.
In Eclipse you can do it simply as follows : Right click on your Java Project and select Export. Select Java -> Runnable JAR file -> Next.
We can imagine a . jar file as a zipped file(. zip) that is created by using WinZip software.
It turns out that JarOutputStream
has three undocumented quirks:
Here is the correct way to create a Jar file:
public void run() throws IOException { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); JarOutputStream target = new JarOutputStream(new FileOutputStream("output.jar"), manifest); add(new File("inputDirectory"), target); target.close(); } private void add(File source, JarOutputStream target) throws IOException { String name = source.getPath().replace("\\", "/"); if (source.isDirectory()) { if (!name.endsWith("/")) { name += "/"; } JarEntry entry = new JarEntry(name); entry.setTime(source.lastModified()); target.putNextEntry(entry); target.closeEntry(); for (File nestedFile : source.listFiles()) { add(nestedFile, target); } } else { JarEntry entry = new JarEntry(name); entry.setTime(source.lastModified()); target.putNextEntry(entry); try (BufferedInputStream 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(); } } }
There's another "quirk" to pay attention: All JarEntry's names should NOT begin with "/".
For example: The jar entry name for the manifest file is "META-INF/MANIFEST.MF" and not "/META-INF/MANIFEST.MF".
The same rule should be followed for all jar entries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With