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

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
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
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
160
459
247
21
Mìlhüsa
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:

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
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
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
160
459
247
21
Mìlhüsa
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.
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
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
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
160
459
247
21
Mìlhüsa
É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.
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
É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 ?
 

robin4002

Expert en informatique et systèmes d'information
Staff
Responsable technique
Responsable forum
12 Novembre 2012
20 819
156
3 000
347
26
Alsace
www.minecraftforgefrance.fr
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.
 

Alex Fatta

Commandant de la Flotte et de la Horde
13 Août 2014
1 391
1
191
187
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 :confused: 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