web-dev-qa-db-fra.com

Comment utiliser JarOutputStream pour créer un fichier JAR?

Comment créer un fichier JAR par programme en utilisant Java.util.jar.JarOutputStream? Le fichier JAR produit par mon programme semble correct (il extrait très bien) mais lorsque j'essaie de charger une bibliothèque à partir de celui-ci Java se plaint qu'il ne peut pas trouver les fichiers qui sont clairement stockés à l'intérieur. Si j'extrait le Fichier JAR et utilisez l'outil de ligne de commande jar de Sun pour le recompresser, la bibliothèque résultante fonctionne très bien. En bref, quelque chose ne va pas avec mon fichier JAR.

Veuillez expliquer comment créer un fichier JAR par programme, avec un fichier manifeste.

53
Gili

Il s'avère que JarOutputStream a trois bizarreries non documentées:

  1. Les noms de répertoire doivent se terminer par une barre oblique "/".
  2. Les chemins doivent utiliser des barres obliques '/', pas '\'
  3. Les entrées ne peuvent pas commencer par une barre oblique "/".

Voici la bonne façon de créer un fichier 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();
  }
}
93
Gili

Il y a une autre "bizarrerie" à faire attention: tous les noms de JarEntry ne doivent PAS commencer par "/".

Par exemple: Le nom d'entrée du fichier JAR pour le fichier manifeste est "META-INF/MANIFEST.MF" et non "/META-INF/MANIFEST.MF".

La même règle doit être suivie pour toutes les entrées de bocal.

Vous pouvez le faire avec ce code:

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 variable: chemin d'accès au fichier JAR

FILE variable: nom et format

2
Muskovets

Voici un exemple de code pour créer un fichier JAR à l'aide de JarOutputStream:

2
ars