web-dev-qa-db-fra.com

Comment décompresser des fichiers récursivement en Java?

J'ai un fichier Zip qui contient d'autres fichiers Zip.

Par exemple, le fichier courrier est abc.Zip et il contient xyz.Zip, class1.Java, class2.Java. Et xyz.Zip contient le fichier class3.Java et class4.Java.

J'ai donc besoin d'extraire le fichier Zip en utilisant Java dans un dossier qui devrait contenir class1.Java, class2.Java, class3.Java et class4.Java.

31
Anish

Attention, le code ici est correct pour les fichiers Zip de confiance, il n'y a pas de validation de chemin avant l'écriture qui peut conduire à une vulnérabilité de sécurité comme décrit dans Zip-slip-vulnérabilité si vous l'utilisez pour dégonfler un fichier Zip téléchargé de client inconnu.


Cette solution est très similaire aux solutions précédentes déjà publiées, mais celle-ci recrée la bonne structure de dossiers lors de la décompression.

static public void extractFolder(String zipFile) throws ZipException, IOException 
{
    System.out.println(zipFile);
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile Zip = new ZipFile(file);
    String newPath = zipFile.substring(0, zipFile.length() - 4);

    new File(newPath).mkdir();
    Enumeration zipFileEntries = Zip.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements())
    {
        // grab a Zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
        String currentEntry = entry.getName();
        File destFile = new File(newPath, currentEntry);
        //destFile = new File(newPath, destFile.getName());
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();

        if (!entry.isDirectory())
        {
            BufferedInputStream is = new BufferedInputStream(Zip
            .getInputStream(entry));
            int currentByte;
            // establish buffer for writing file
            byte data[] = new byte[BUFFER];

            // write the current file to disk
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedOutputStream dest = new BufferedOutputStream(fos,
            BUFFER);

            // read and write until last byte is encountered
            while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();
            is.close();
        }

        if (currentEntry.endsWith(".Zip"))
        {
            // found a Zip file, try to open
            extractFolder(destFile.getAbsolutePath());
        }
    }
}
72
NeilMonday

Voici une base de code non testée sur un ancien code que j'avais des fichiers décompressés.

public void doUnzip(String inputZip, String destinationDirectory)
        throws IOException {
    int BUFFER = 2048;
    List zipFiles = new ArrayList();
    File sourceZipFile = new File(inputZip);
    File unzipDestinationDirectory = new File(destinationDirectory);
    unzipDestinationDirectory.mkdir();

    ZipFile zipFile;
    // Open Zip file for reading
    zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);

    // Create an enumeration of the entries in the Zip file
    Enumeration zipFileEntries = zipFile.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements()) {
        // grab a Zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();

        String currentEntry = entry.getName();

        File destFile = new File(unzipDestinationDirectory, currentEntry);
        destFile = new File(unzipDestinationDirectory, destFile.getName());

        if (currentEntry.endsWith(".Zip")) {
            zipFiles.add(destFile.getAbsolutePath());
        }

        // grab file's parent directory structure
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();

        try {
            // extract file if not a directory
            if (!entry.isDirectory()) {
                BufferedInputStream is =
                        new BufferedInputStream(zipFile.getInputStream(entry));
                int currentByte;
                // establish buffer for writing file
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest =
                        new BufferedOutputStream(fos, BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
                is.close();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    zipFile.close();

    for (Iterator iter = zipFiles.iterator(); iter.hasNext();) {
        String zipName = (String)iter.next();
        doUnzip(
            zipName,
            destinationDirectory +
                File.separatorChar +
                zipName.substring(0,zipName.lastIndexOf(".Zip"))
        );
    }

}
9
Charlie

Je prends ca.anderson4 et supprime la liste des fichiers zip et réécris un peu, voici ce que j'ai obtenu:

public class Unzip {

public void unzip(String zipFile) throws ZipException,
        IOException {

    System.out.println(zipFile);;
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile Zip = new ZipFile(file);
    String newPath = zipFile.substring(0, zipFile.length() - 4);

    new File(newPath).mkdir();
    Enumeration zipFileEntries = Zip.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements()) {
        // grab a Zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();

        String currentEntry = entry.getName();

        File destFile = new File(newPath, currentEntry);
        destFile = new File(newPath, destFile.getName());
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();
        if (!entry.isDirectory()) {
            BufferedInputStream is = new BufferedInputStream(Zip
                    .getInputStream(entry));
            int currentByte;
            // establish buffer for writing file
            byte data[] = new byte[BUFFER];

            // write the current file to disk
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedOutputStream dest = new BufferedOutputStream(fos,
                    BUFFER);

            // read and write until last byte is encountered
            while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();
            is.close();
        }
        if (currentEntry.endsWith(".Zip")) {
            // found a Zip file, try to open
            unzip(destFile.getAbsolutePath());
        }
    }
}

public static void main(String[] args) {
    Unzip unzipper=new Unzip();
    try {
        unzipper.unzip("test/test.Zip");
    } catch (ZipException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

J'ai testé et ça marche

6
fero46

Modifié selon mes besoins, puis mélangé à quelques-unes des meilleures réponses. Cette version:

  • Extraire récursivement un Zip à un emplacement donné

  • Créer des répertoires vides

  • Fermer correctement Zip


public static void unZipAll(File source, File destination) throws IOException 
{
    System.out.println("Unzipping - " + source.getName());
    int BUFFER = 2048;

    ZipFile Zip = new ZipFile(source);
    try{
        destination.getParentFile().mkdirs();
        Enumeration zipFileEntries = Zip.entries();

        // Process each entry
        while (zipFileEntries.hasMoreElements())
        {
            // grab a Zip file entry
            ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
            String currentEntry = entry.getName();
            File destFile = new File(destination, currentEntry);
            //destFile = new File(newPath, destFile.getName());
            File destinationParent = destFile.getParentFile();

            // create the parent directory structure if needed
            destinationParent.mkdirs();

            if (!entry.isDirectory())
            {
                BufferedInputStream is = null;
                FileOutputStream fos = null;
                BufferedOutputStream dest = null;
                try{
                    is = new BufferedInputStream(Zip.getInputStream(entry));
                    int currentByte;
                    // establish buffer for writing file
                    byte data[] = new byte[BUFFER];

                    // write the current file to disk
                    fos = new FileOutputStream(destFile);
                    dest = new BufferedOutputStream(fos, BUFFER);

                    // read and write until last byte is encountered
                    while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                        dest.write(data, 0, currentByte);
                    }
                } catch (Exception e){
                    System.out.println("unable to extract entry:" + entry.getName());
                    throw e;
                } finally{
                    if (dest != null){
                        dest.close();
                    }
                    if (fos != null){
                        fos.close();
                    }
                    if (is != null){
                        is.close();
                    }
                }
            }else{
                //Create directory
                destFile.mkdirs();
            }

            if (currentEntry.endsWith(".Zip"))
            {
                // found a Zip file, try to extract
                unZipAll(destFile, destinationParent);
                if(!destFile.delete()){
                    System.out.println("Could not delete Zip");
                }
            }
        }
    } catch(Exception e){
        e.printStackTrace();
        System.out.println("Failed to successfully unzip:" + source.getName());
    } finally {
        Zip.close();
    }
    System.out.println("Done Unzipping:" + source.getName());
}
2
Matthew Pautzke

Lors des tests, j'ai remarqué que File.mkDirs () ne fonctionne pas sous Windows ...

/ ** * pour un nom de chemin complet donné recrée tous les répertoires parents ** /

    private void createParentHierarchy(String parentName) throws IOException {
        File parent = new File(parentName);
        String[] parentsStrArr = parent.getAbsolutePath().split(File.separator == "/" ? "/" : "\\\\");

        //create the parents of the parent
        for(int i=0; i < parentsStrArr.length; i++){
            StringBuffer currParentPath = new StringBuffer();
            for(int j = 0; j < i; j++){
                currParentPath.append(parentsStrArr[j]+File.separator);
            }
            File currParent = new File(currParentPath.toString());
            if(!currParent.isDirectory()){
                boolean created = currParent.mkdir();
                if(isVerbose)log("creating directory "+currParent.getAbsolutePath());
            }
        }

        //create the parent itself
        if(!parent.isDirectory()){
            boolean success = parent.mkdir();
        }
    }
2
boxymoron

On devrait FERMER le fichier Zip après décompresser.

static public void extractFolder(String zipFile) throws ZipException, IOException 
{
    System.out.println(zipFile);
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile Zip = new ZipFile(file);
    try
    { 
       ...code from other answers ( ex. NeilMonday )...
    }
    finally
    {
        Zip.close();
    }
}
1
Igor Shakola

Identique à la réponse de NeilMonday, mais extrait les répertoires vides:

static public void extractFolder(String zipFile) throws ZipException, IOException 
{
    System.out.println(zipFile);
    int BUFFER = 2048;
    File file = new File(zipFile);

    ZipFile Zip = new ZipFile(file);
    String newPath = zipFile.substring(0, zipFile.length() - 4);

    new File(newPath).mkdir();
    Enumeration zipFileEntries = Zip.entries();

    // Process each entry
    while (zipFileEntries.hasMoreElements())
    {
        // grab a Zip file entry
        ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
        String currentEntry = entry.getName();
        File destFile = new File(newPath, currentEntry);
        //destFile = new File(newPath, destFile.getName());
        File destinationParent = destFile.getParentFile();

        // create the parent directory structure if needed
        destinationParent.mkdirs();

        if (!entry.isDirectory())
        {
            BufferedInputStream is = new BufferedInputStream(Zip
            .getInputStream(entry));
            int currentByte;
            // establish buffer for writing file
            byte data[] = new byte[BUFFER];

            // write the current file to disk
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedOutputStream dest = new BufferedOutputStream(fos,
            BUFFER);

            // read and write until last byte is encountered
            while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();
            is.close();
        }
        else{
            destFile.mkdirs()
        }
        if (currentEntry.endsWith(".Zip"))
        {
            // found a Zip file, try to open
            extractFolder(destFile.getAbsolutePath());
        }
    }
}
0
James Scriven