web-dev-qa-db-fra.com

Comment écrire un programme Java qui peut extraire un fichier JAR et stocker ses données dans le répertoire spécifié (emplacement)?

J'ai créé un fichier JAR . Maintenant, j'ai créé un autre programme Java. Je veux décompresser ce fichier JAR dans un autre répertoire, ce qui signifie que je veux faire quelque chose comme décompresser.

Si je lance jar -xf filename.jar cela provoque une erreur:

Exception in thread "main" Java.io.IOException: Cannot run program "jar": 
Java.io.IOException: error=2, No such file or directory
     at Java.lang.ProcessBuilder.start(ProcessBuilder.Java:459)
     at Java.lang.Runtime.exec(Runtime.Java:593)`
30

Adaptez cet exemple: Comment extraire Java des archives JAR et Zip

Ou essayez ce code:

Extraire le contenu des fichiers Zip/JAR par programme

Supposons que jarFile est le fichier jar/Zip à extraire. destDir est le chemin où il sera extrait:

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

61
JuanZe

Vous pouvez utiliser cet extrait de code comme référence pour effectuer votre tâche.Il est presque le même que l'extrait de code illustré ci-dessus par @JuanZe, sauf que pour ceux qui recevaient l'exception FileNotFoundException, j'ai ajouté un petit extrait de code qui vérifiera si le existe et s'il ne l'est pas, il créera le dossier parent avec les fichiers et extraira le contenu du fichier jar dans le dossier de destination spécifié.

Extrait de code:

public class JarDemo {

  public static void main(String[] args) throws Java.io.IOException {
    Java.util.jar.JarFile jarfile = new Java.util.jar.JarFile(new Java.io.File("E:/sqljdbc4.jar")); //jar file path(here sqljdbc4.jar)
    Java.util.Enumeration<Java.util.jar.JarEntry> enu= jarfile.entries();
    while(enu.hasMoreElements())
    {
        String destdir = "E:/abc/";     //abc is my destination directory
        Java.util.jar.JarEntry je = enu.nextElement();

        System.out.println(je.getName());

        Java.io.File fl = new Java.io.File(destdir, je.getName());
        if(!fl.exists())
        {
            fl.getParentFile().mkdirs();
            fl = new Java.io.File(destdir, je.getName());
        }
        if(je.isDirectory())
        {
            continue;
        }
        Java.io.InputStream is = jarfile.getInputStream(je);
        Java.io.FileOutputStream fo = new Java.io.FileOutputStream(fl);
        while(is.available()>0)
        {
            fo.write(is.read());
        }
        fo.close();
        is.close();
    }

  }

}
8
Arpit

JarFile classe.

JarFile file = new JarFile("file.jar");   
for (Enumeration<JarEntry> enum = file.entries(); enum.hasMoreElements();) {   
    JarEntry entry = enum.next();   
    System.out.println(entry.getName());   
} 
5
adatapost

Voici ce que je ferais pour extraire tout mon dossier "ressources" de mon pot. Il est beaucoup plus rapide d'utiliser BufferedReader et BufferedWriter.

 public static boolean extractResourcesToTempFolder() {
    try {
        //If folder exist, delete it.
        String destPath = getTempDir() + File.separator + "JToolkit" + File.separator;
        deleteDirectoryRecursive(new File(destPath));            

        JarFile jarFile = new JarFile(JToolkit.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        Enumeration<JarEntry> enums = jarFile.entries();
        while (enums.hasMoreElements()) {
            JarEntry entry = enums.nextElement();
            if (entry.getName().startsWith("resources")) {
                File toWrite = new File(destPath + entry.getName());
                if (entry.isDirectory()) {
                    toWrite.mkdirs();
                    continue;
                }
                InputStream in = new BufferedInputStream(jarFile.getInputStream(entry));
                OutputStream out = new BufferedOutputStream(new FileOutputStream(toWrite));
                byte[] buffer = new byte[2048];
                for (;;) {
                    int nBytes = in.read(buffer);
                    if (nBytes <= 0) {
                        break;
                    }
                    out.write(buffer, 0, nBytes);
                }
                out.flush();
                out.close();
                in.close();
            }
            System.out.println(entry.getName());
        }
    } catch (IOException ex) {
        Logger.getLogger(Methods.class.getName()).log(Level.SEVERE, null, ex);
        return false;
    }
    return true;
}
4
Jamesst20

Vieille question.
Voici une réponse mise à jour utilisant:

  • Java 7 Java.nio pour créer et copier efficacement des entrées
  • Java 8 stream pour trier et collecter les entrées lexicographiquement (afin de toujours créer d'abord des dossiers).

Notez que j'ai utilisé Java.util.Zip.ZipFile (la classe de base) au lieu de Java.util.jar.JarFile (la sous-classe).
Le dernier effectue plus de choses qui ne sont pas nécessaires pour "juste" extraire des fichiers d'une archive.
Cela réduit donc les frais généraux et empêche l'augmentation des exceptions liées à des problèmes de sécurité. Mais si nécessaire, vous pouvez bien sûr remplacer ZipFile/ZipEntry par JarFile/JarEntry.

import Java.io.IOException;
import Java.nio.file.Files;
import Java.nio.file.Path;
import Java.util.Comparator;
import Java.util.List;
import Java.util.stream.Collectors;
import Java.util.Zip.ZipEntry;
import Java.util.Zip.ZipFile;

public class FileUtils {

    public static void extractArchive(Path archiveFile, Path destPath) throws IOException {

        Files.createDirectories(destPath); // create dest path folder(s)

        try (ZipFile archive = new ZipFile(archiveFile.toFile())) {

            // sort entries by name to always create folders first
            List<? extends ZipEntry> entries = archive.stream()
                                                      .sorted(Comparator.comparing(ZipEntry::getName))
                                                      .collect(Collectors.toList());

            // copy each entry in the dest path
            for (ZipEntry entry : entries) {
                Path entryDest = destPath.resolve(entry.getName());

                if (entry.isDirectory()) {
                    Files.createDirectory(entryDest);
                    continue;
                }

                Files.copy(archive.getInputStream(entry), entryDest);
            }
        }

    }
}
2
davidxxx

Votre titre ne semble pas très bien correspondre à la question, mais si vous voulez vraiment "écrire [a] Java extrayant un fichier jar", vous avez juste besoin Class JarFile .

1
DigitalRoss

Vous pouvez utiliser cette bibliothèque très simple pour emballer/décompresser le fichier jar

JarManager

Très simple

import Java.io.File;
import Java.util.List;

import fr.stevecohen.jarmanager.JarUnpacker;

class Test {
   JarUnpacker jarUnpacker = new JarUnpacker(); 
   File myfile = new File("./myfile.jar");
   File unpackDir = new File("./mydir");

   List<File> unpacked_files = jarUnpacker.unpack(myfile.getAbsolutePath(), unpackDir.getAbsolutePath());
}

Vous pouvez également utiliser la dépendance maven

<dependency>
    <groupId>fr.stevecohen.jarmanager</groupId>
    <artifactId>JarManager</artifactId>
    <version>0.5.0</version>
</dependency>

Vous avez également besoin de mon référentiel

<repository>
    <id>repo-reapersoon</id>
    <name>ReaperSoon's repo</name>
    <url>http://repo-maven.stevecohen.fr</url>
</repository>

Vérifiez la dernière version avec le lien ci-dessous pour utiliser la dernière dépendance

Veuillez utiliser mon tracker de problème public si vous trouvez des bugs

1
ReaperSoon

Eh bien voici ma version, en utilisant try-with-resources:

    try (JarFile jarFile = new JarFile(artifact.getFile())) {
        for (JarEntry entry : Collections.list(jarFile.entries())) {
            try (InputStream is = jarFile.getInputStream(entry)) {
                File file = new File(targetDir, entry.getName());
                try (FileOutputStream fos = new FileOutputStream(file)) {
                    fos.write(is.read());
                }
            }
        }
    } catch (IOException e) {
        throw new MyException(String.format(
            "Unable to open jar %s", artifact.getArtifactId()), e);
    }
0
Adam