Как использовать JarOutputStream для создания файла JAR?
Как можно создать файл JAR программно с помощью java.util.jar.JarOutputStream
? Файл JAR, созданный моей программой, выглядит правильно (он отлично извлекается), но когда я пытаюсь загрузить библиотеку из него Java жалуется, что он не может найти файлы, которые четко хранятся внутри него. Если я извлеку файл JAR и использую Sun's jar
инструмент командной строки для повторного сжатия результирующая библиотека работает нормально. Короче говоря, что-то не так с моим файлом JAR.
пожалуйста, объясните, как создать файл JAR программно, в комплекте с файлом манифеста.
4 ответа:
получается, что
JarOutputStream
имеет три недокументированные причуды:
- имена каталогов должны заканчиваться косой чертой'/'.
- пути должны использовать ' / 'косые черты, а не'\'
- записи не могут начинаться с косой черты'/'.
вот правильный способ создания файла Jar:
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 { BufferedInputStream in = null; try { if (source.isDirectory()) { 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()) add(nestedFile, target); return; } JarEntry entry = new JarEntry(source.getPath().replace("\", "/")); 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(); } finally { if (in != null) in.close(); } }
есть еще одна "причуда", чтобы обратить внимание: все имена JarEntry не должны начинаться с"/".
например: имя записи jar для файла манифеста - " META-INF/MANIFEST.MF "and not" /META-INF / MANIFEST.МФ."
то же самое правило должно соблюдаться для всех записей jar.
вы можете сделать это с помощью этого кода:
public void write(File[] files, String comment) throws IOException { FileOutputStream fos = new FileOutputStream(PATH + FILE); JarOutputStream jos = new JarOutputStream(fos, manifest); BufferedOutputStream bos = new BufferedOutputStream(jos); jos.setComment(comment); for (File f : files) { print("Writing file: " + f.toString()); BufferedReader br = new BufferedReader(new FileReader(f)); jos.putNextEntry(new JarEntry(f.getName())); int c; while ((c = br.read()) != -1) { bos.write(c); } br.close(); bos.flush(); } bos.close(); // JarOutputStream jor = new JarOutputStream(new FileOutputStream(PATH + FILE), manifest); }
PATH
переменная: путь к файлу JAR
FILE
переменной: имя и формат