Résolu Java : extraction d'un zip fichiers + dossiers

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 389
1
191
187
Bonjour !

Je reviens ici pour essayer de trouver une solution mon problème sur lequel je galère depuis plusieurs heures sans trouver de réponse.

Bon je cherche à extraire un fichier compressé qui contient des fichiers .jar ou des dossiers contenant eux mêmes des fichiers .jar.

Pour ce faire, j'utilise le code suivante :

Code:
    public static void getZipFiles(String filename) {
        try {
            String destinationname = CheckModPackFolder.getModpackfolderpath();
            byte[] buf = new byte[1024];
            ZipInputStream zipinputstream = null;
            ZipEntry zipentry;
            zipinputstream = new ZipInputStream(new FileInputStream(destinationname + filename));

            zipentry = zipinputstream.getNextEntry();
            while (zipentry != null) {
                //for each entry to be extracted
                String entryName = destinationname + zipentry.getName();
                entryName = entryName.replace('/', File.separatorChar);
                entryName = entryName.replace('\\', File.separatorChar);
                System.out.println("entryname " + entryName);
                int n;
                FileOutputStream fileoutputstream;
                File newFile = new File(entryName);
                if (zipentry.isDirectory()) {
                    if (!newFile.mkdirs()) {
                    }
                    zipentry = zipinputstream.getNextEntry();
                    continue;
                }

                fileoutputstream = new FileOutputStream(entryName);

                while ((n = zipinputstream.read(buf, 0, 1024)) > -1) {
                    fileoutputstream.write(buf, 0, n);
                }

                fileoutputstream.close();
                zipinputstream.closeEntry();
                zipentry = zipinputstream.getNextEntry();

            }//while

            zipinputstream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Sauf que le code plante à l'extraction d'un fichier .jar et je me retrouve avec un FileNotFoundException que je ne parviens pas à résoudre.

Le ZIP se compose de la manière suivante :

Mods:
1.7.10: (dossier)
fichiers JAR. <--Le code plante ici en me disant que le chemin d'accès .../mods/1.7.10/nom_du_jar est introuvable.
ic2: (dossier)
fichiers JAR

Fichiers JAR.

Avec ce code, après exécution de la commande, je n'obtiens qu'un fichier nommé "mods" (sans format) qui fait 0 octets. Je suis bloqué donc je me tourne vers vous en espérant trouver de l'aide :)

Voilà !

AlexFatta
 
Désolé du temps de réponse,

Si je comprends bien tu tentes d'extraire un fichier dans un fichier jar lui-même contenus dans un autre fichier jar ?

Est-ce que le chemin du fichier jar contenant le fichier est connu, idem pour le chemin du fichier à extraire ? En gros comment tu fais pour qu'il trouve le fichier à extraire.

Et sinon, ton erreur est que tu fait un
Code:
File newFile = new File(entryName);

entryName est le nom du fichier dans le zip, et là il tente de chercher ce fichier à la racine de ton projet, alors qu'il est dans un zip. Il faut faire une manip pour lire un fichier dans un zip, que je te donnerais quand je saurais plus sur ce que tu veut faire ^c^

Cordialement,
ShE3py.
 
Dernière édition:
Bonjour !

Non en fait le fichier à extraire n'est pas dans le JAR executable. Le programme télécharge le ZIP depuis un site internet et l'extrait ensuite. Dans ce ZIP, il y a un dossier "mods" qui contient lui même tous le mods en .jar. Je souhaiterai extraire le dossier dans le même dossier que le zip. Et c'est en effectuant l'extraction que ca coince.

Donc entre temps j'ai fait quelque test : le code que j'utilise fonctionne très bien si il n'y a pas de dossier. Si il y a un dossier, ca ne fonctionne pas. De même, j'ai trouvé une API qui s'occupe des JAR : zip4J. Je me suis donc penché dessus vu la simplicité et la limpidité de l'API. Là encore, sans dossier, ca fonctionne très bien, mais si je met un dossier, ca plante :/

Voilà tu sais tout ! :D Je vais essayer de tester en modifiant le chemin d'accès de entryName, je ferai comme je pourrais ;)

Dans l'attente de ta réponse ;)

AlexFatta
 
Code:
public static void extract(final File zip, final File toFolder) throws IOException {   
   ZipInputStream istream = new ZipInputStream(new FileInputStream(zip));
   byte[] buffer = new byte[1028];
   
   ZipEntry entry = istream.getNextEntry();
   while(entry != null) {
       final String fileName = entry.getName();
       final File out = new File(toFolder.getAbsolutePath() + "/" + fileName);
       out.getParentFile().mkdirs();
       
       final FileOutputStream ostream = new FileOutputStream(out);
       
       int len;
       while((len = istream.read(buffer)) > 0) ostream.write(buffer, 0, len);
           
       ostream.close();
       entry = istream.getNextEntry();
   }
       
   istream.close();
}

Voilà, cette fonction extrait le zip zip dans le dossier toFolder.
Niveau explication c'est pas très compliqué, d'abord on créer un flux afin de lire le zip, ensuite tant qu'il y a une nouvelle entré ont récupère son nom (fileName contient aussi le chemin dans le zip), on créez le fichier où sera copier le fichier puis ont le mkdirs (on créer les dossiers), ensuite on créer un flux pour écrire dans ce fichier, et tant qu'on peut lire dans le flux du zip on lit et écrit dans le flux du fichier.

C'est pas très optimisé, ont pourrais rajouter des trucs comme des buffers mais sa fonctionne.

Cordialement,
ShE3py.
 
Bonjour !

Bon en premier merci @ShE3py pour le code. Je l'ai incorporé et j'ai une erreur en sortie que voici :
Code:
java.io.FileNotFoundException: C:\Users\asus\AppData\Roaming\.minecraft\Modpack\FeedTheWishS4\mods\adv-repulsion-systems-59.0.4.jar (Le chemin dメacc│s sp←cifi← est introuvable)
    at java.base/java.io.FileOutputStream.open0(Native Method)
    at java.base/java.io.FileOutputStream.open(Unknown Source)
    at java.base/java.io.FileOutputStream.<init>(Unknown Source)
    at java.base/java.io.FileOutputStream.<init>(Unknown Source)
    at fr.alexfatta.ftbWizard.extractFiles.UnzipFileClass.extract(UnzipFileClass.java:74)
    at fr.alexfatta.ftbWizard.WindowsApp$2.actionPerformed(WindowsApp.java:102)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
    at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.desktop/java.awt.Component.processEvent(Unknown Source)
    at java.desktop/java.awt.Container.processEvent(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.EventQueue.access$600(Unknown Source)
    at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

La ligne 74 est la suivante :
Code:
final FileOutputStream ostream = new FileOutputStream(out);

Voila ! :D Si tu as une solution ou une piste ^^ ;)

AlexFatta
 
Étrange, le new FileOutupStream(out) lancer un FileNotFoundException quand le dossier n'existe pas, mais je mkdirs() le dossier juste avant.

Le programme a-t-il accès au dossier ? Normalement il devrait y avoir un SecurityException s'il ne peut créer le fichier/dossier.
 
Étrange, le new FileOutupStream(out) lancer un FileNotFoundException quand le dossier n'existe pas, mais je mkdirs() le dossier juste avant.

Le programme a-t-il accès au dossier ? Normalement il devrait y avoir un SecurityException s'il ne peut créer le fichier/dossier.
C'est la seule exception présente dans les logs. Mais je peux lancer en admin et te donner la réponse je fais ça de suite ;)

AlexFatta

EDIT : suis-je bête....lancer un programme java en admin...pas possible. Comment je lui accorde la permission de le faire ?
 
Ce n'est pas un problème de permission, le soucis c'est que le chemin indiqué n'existe pas (surement car le dossier mods n'est pas créé lorsqu'il essaie d'écrire).

Tu peux lancer un cmd en admin et taper la commande java dedans.
 
Bonjour !

Tu peux lancer un cmd en admin et taper la commande java dedans.
Pas compris ce que je dois exécuter :/

Après dans le code j'ai essayé une "feinte" pour créer le dossier mods :
Code:
if (out.getParentFile().mkdirs()) {}

Mais ca ne fonctionne pas, toujours la même erreur, et en prime (ca le faisait avant déjà) il y a un fichier "mods' de 0 octets sans extension qui se crée. :/ C'est juste une extraction de dossier et il galère xD

Mais c'est vrai que même en créant le dossier mods il plante c'est chelou o_O Pourtant dans les logs on voit bien le bon chemin d'accès :/ Mais ce que je trouve étrange c'est qu'à la fin de l'erreur il met le nom du mod alors qu'il arrive pas à créer ni même trouver le dossier mods :/

AlexFatta