web-dev-qa-db-fra.com

comment compresser un dossier en java

Supposons que j'ai la structure de répertoire suivante. 

D:\reports\january\

En janvier, supposons que deux fichiers Excel disent A.xls et B.xls. Il existe de nombreux endroits où il a été écrit sur la façon de compresser des fichiers en utilisant Java.util.Zip. Mais je veux compresser le dossier de janvier lui-même dans le dossier des rapports afin que les deux janvier et janvier.Zip soient présents dans les rapports. (Cela signifie que lorsque je décompresse le fichier jan.zip, je devrais obtenir le dossier janvier). 

Quelqu'un peut-il s'il vous plaît me fournir le code pour le faire en utilisant Java.util.Zip. S'il vous plaît laissez-moi savoir si cela peut être plus facilement fait en utilisant d'autres bibliothèques. 

Merci beaucoup...

55
mukund

Il peut être facilement résolu par le paquet Java.util.Zip pas besoin de fichiers Jar supplémentaires 

Copiez simplement le code suivant et run it avec votre IDE 

//Import all needed packages
package general;
import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.util.ArrayList;
import Java.util.List;
import Java.util.Zip.ZipEntry;
import Java.util.Zip.ZipOutputStream;

public class ZipUtils {

    private List <String> fileList;
    private static final String OUTPUT_Zip_FILE = "Folder.Zip";
    private static final String SOURCE_FOLDER = "D:\\Reports"; // SourceFolder path

    public ZipUtils() {
        fileList = new ArrayList < String > ();
    }

    public static void main(String[] args) {
        ZipUtils appZip = new ZipUtils();
        appZip.generateFileList(new File(SOURCE_FOLDER));
        appZip.zipIt(OUTPUT_Zip_FILE);
    }

    public void zipIt(String zipFile) {
        byte[] buffer = new byte[1024];
        String source = new File(SOURCE_FOLDER).getName();
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(fos);

            System.out.println("Output to Zip : " + zipFile);
            FileInputStream in = null;

            for (String file: this.fileList) {
                System.out.println("File Added : " + file);
                ZipEntry ze = new ZipEntry(source + File.separator + file);
                zos.putNextEntry(ze);
                try {
                    in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
                    int len;
                    while ((len = in .read(buffer)) > 0) {
                        zos.write(buffer, 0, len);
                    }
                } finally {
                    in.close();
                }
            }

            zos.closeEntry();
            System.out.println("Folder successfully compressed");

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                zos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void generateFileList(File node) {
        // add file only
        if (node.isFile()) {
            fileList.add(generateZipEntry(node.toString()));
        }

        if (node.isDirectory()) {
            String[] subNote = node.list();
            for (String filename: subNote) {
                generateFileList(new File(node, filename));
            }
        }
    }

    private String generateZipEntry(String file) {
        return file.substring(SOURCE_FOLDER.length() + 1, file.length());
    }
}

Référez-vous mkyong .. J'ai changé le code pour l'exigence de la question actuelle

48
kark

Avez-vous essayé Zeroturnaround Zip library? C'est vraiment chouette! Zip un dossier est juste un one liner:

ZipUtil.pack(new File("D:\\reports\\january\\"), new File("D:\\reports\\january.Zip"));

(merci à Oleg Šelajev pour l'exemple)

81
Petro Semeniuk

Voici l'exemple de Java 8+:

public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
    Path p = Files.createFile(Paths.get(zipFilePath));
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) {
        Path pp = Paths.get(sourceDirPath);
        Files.walk(pp)
          .filter(path -> !Files.isDirectory(path))
          .forEach(path -> {
              ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
              try {
                  zs.putNextEntry(zipEntry);
                  Files.copy(path, zs);
                  zs.closeEntry();
            } catch (IOException e) {
                System.err.println(e);
            }
          });
    }
}
62
Nikita Koksharov

Voici une solution assez succincte pour Java 7+ qui repose uniquement sur les classes Vanilla JDK. Aucune bibliothèque tierce n'est requise:

public static void pack(final Path folder, final Path zipFilePath) throws IOException {
    try (
            FileOutputStream fos = new FileOutputStream(zipFilePath.toFile());
            ZipOutputStream zos = new ZipOutputStream(fos)
    ) {
        Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                zos.putNextEntry(new ZipEntry(folder.relativize(file).toString()));
                Files.copy(file, zos);
                zos.closeEntry();
                return FileVisitResult.CONTINUE;
            }

            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                zos.putNextEntry(new ZipEntry(folder.relativize(dir).toString() + "/"));
                zos.closeEntry();
                return FileVisitResult.CONTINUE;
            }
        });
    }
}

Il copie tous les fichiers dans folder, y compris les répertoires vides, et crée une archive Zip à zipFilePath.

31
jjst

Java 7+, commons.io

public final class ZipUtils {

    public static void zipFolder(final File folder, final File zipFile) throws IOException {
        zipFolder(folder, new FileOutputStream(zipFile));
    }

    public static void zipFolder(final File folder, final OutputStream outputStream) throws IOException {
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {
            processFolder(folder, zipOutputStream, folder.getPath().length() + 1);
        }
    }

    private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength)
            throws IOException {
        for (final File file : folder.listFiles()) {
            if (file.isFile()) {
                final ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength));
                zipOutputStream.putNextEntry(zipEntry);
                try (FileInputStream inputStream = new FileInputStream(file)) {
                    IOUtils.copy(inputStream, zipOutputStream);
                }
                zipOutputStream.closeEntry();
            } else if (file.isDirectory()) {
                processFolder(file, zipOutputStream, prefixLength);
            }
        }
    }
}
10
Tony BenBrahim

J'utilise généralement une classe d'assistance que j'ai écrite une fois pour cette tâche:

import Java.util.Zip.*;
import Java.io.*;

public class ZipExample {
    public static void main(String[] args){
        ZipHelper zippy = new ZipHelper();
        try {
            zippy.zipDir("folderName","test.Zip");
        } catch(IOException e2) {
            System.err.println(e2);
        }
    }
}

class ZipHelper  
{
    public void zipDir(String dirName, String nameZipFile) throws IOException {
        ZipOutputStream Zip = null;
        FileOutputStream fW = null;
        fW = new FileOutputStream(nameZipFile);
        Zip = new ZipOutputStream(fW);
        addFolderToZip("", dirName, Zip);
        Zip.close();
        fW.close();
    }

    private void addFolderToZip(String path, String srcFolder, ZipOutputStream Zip) throws IOException {
        File folder = new File(srcFolder);
        if (folder.list().length == 0) {
            addFileToZip(path , srcFolder, Zip, true);
        }
        else {
            for (String fileName : folder.list()) {
                if (path.equals("")) {
                    addFileToZip(folder.getName(), srcFolder + "/" + fileName, Zip, false);
                } 
                else {
                     addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, Zip, false);
                }
            }
        }
    }

    private void addFileToZip(String path, String srcFile, ZipOutputStream Zip, boolean flag) throws IOException {
        File folder = new File(srcFile);
        if (flag) {
            Zip.putNextEntry(new ZipEntry(path + "/" +folder.getName() + "/"));
        }
        else {
            if (folder.isDirectory()) {
                addFolderToZip(path, srcFile, Zip);
            }
            else {
                byte[] buf = new byte[1024];
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                Zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
                while ((len = in.read(buf)) > 0) {
                    Zip.write(buf, 0, len);
                }
            }
        }
    }
}
7
halex

J'utiliserais Apache Ant , qui dispose d'une API pour appeler des tâches à partir de code Java plutôt que d'un fichier de construction XML.

Project p = new Project();
p.init();
Zip zip = new Zip();
Zip.setProject(p);
Zip.setDestFile(zipFile); // a Java.io.File for the Zip you want to create
Zip.setBasedir(new File("D:\\reports"));
Zip.setIncludes("january/**");
Zip.perform();

Ici, je lui dis de commencer à partir du répertoire de base D:\reports et de compresser le dossier january et tout ce qu’il contient. Les chemins dans le fichier Zip résultant seront les mêmes que les chemins d'origine relatifs à D:\reports, ils incluront donc le préfixe january.

4
Ian Roberts

Exemple Java 8+ amélioré (extrait de réponse de Nikita Koksharov )

public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
    Path p = Files.createFile(Paths.get(zipFilePath));
    Path pp = Paths.get(sourceDirPath);
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p));
        Stream<Path> paths = Files.walk(pp)) {
        paths
          .filter(path -> !Files.isDirectory(path))
          .forEach(path -> {
              ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
              try {
                  zs.putNextEntry(zipEntry);
                  Files.copy(path, zs);
                  zs.closeEntry();
            } catch (IOException e) {
                System.err.println(e);
            }
          });
    }
}

Files.walk a été encapsulé dans un bloc try with resources afin que le flux puisse être fermé. Ceci résout le problème de bloqueur identifié par SonarQube. Merci @Matt Harrison pour avoir signalé cela.

3
Abdul Rauf

Essaye ça:

 import Java.io.File;

 import Java.io.FileInputStream;

 import Java.io.FileOutputStream;

 import Java.util.Zip.ZipEntry;

 import Java.util.Zip.ZipOutputStream;


  public class Zip {

public static void main(String[] a) throws Exception {

    zipFolder("D:\\reports\\january", "D:\\reports\\january.Zip");

  }

  static public void zipFolder(String srcFolder, String destZipFile) throws Exception {
    ZipOutputStream Zip = null;
    FileOutputStream fileWriter = null;
    fileWriter = new FileOutputStream(destZipFile);
    Zip = new ZipOutputStream(fileWriter);
    addFolderToZip("", srcFolder, Zip);
    Zip.flush();
    Zip.close();
  }
  static private void addFileToZip(String path, String srcFile, ZipOutputStream Zip)
      throws Exception {
    File folder = new File(srcFile);
    if (folder.isDirectory()) {
      addFolderToZip(path, srcFile, Zip);
    } else {
      byte[] buf = new byte[1024];
      int len;
      FileInputStream in = new FileInputStream(srcFile);
      Zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
      while ((len = in.read(buf)) > 0) {
        Zip.write(buf, 0, len);
      }
    }
  }

  static private void addFolderToZip(String path, String srcFolder, ZipOutputStream Zip)
      throws Exception {
    File folder = new File(srcFolder);

    for (String fileName : folder.list()) {
      if (path.equals("")) {
        addFileToZip(folder.getName(), srcFolder + "/" + fileName, Zip);
      } else {
        addFileToZip(path + "/" + folder.getName(), srcFolder + "/" +   fileName, Zip);
      }
    }
  }



   }
2
Denis

Java 6 +

import Java.io.*;
import Java.util.Zip.ZipEntry;
import Java.util.Zip.ZipOutputStream;

public class Zip {

    private static final FileFilter FOLDER_FILTER = new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isDirectory();
        }
    };

    private static final FileFilter FILE_FILTER = new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isFile();
        }
    };


    private static void compress(File file, ZipOutputStream outputStream, String path) throws IOException {

        if (file.isDirectory()) {
            File[] subFiles = file.listFiles(FILE_FILTER);
            if (subFiles != null) {
                for (File subFile : subFiles) {
                    compress(subFile, outputStream, new File(path, subFile.getName()).getAbsolutePath());
                }
            }
            File[] subDirs = file.listFiles(FOLDER_FILTER);
            if (subDirs != null) {
                for (File subDir : subDirs) {
                    compress(subDir, outputStream, new File(path, subDir.getName()).getAbsolutePath());
                }
            }
        } else if (file.exists()) {
            outputStream.putNextEntry(new ZipEntry(path));
            FileInputStream inputStream = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) >= 0) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.closeEntry();
        }
    }

    public static void compress(String dirPath, String zipFilePath) throws IOException {
        File file = new File(dirPath);
        final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFilePath));
        compress(file, outputStream, "/");
        outputStream.close();
    }

}
1
Dillion Wang

En utilisant Zip4j vous pouvez simplement faire ceci

ZipFile zipfile = new ZipFile(new File("D:\\reports\\january\\filename.Zip"));
zipfile.addFolder(new File("D:\\reports\\january\\"));

Il archivera votre dossier et tout ce qu'il contient.

Utilisez la méthode .extractAll pour tout comprendre:

zipfile.extractAll("D:\\destination_directory");
1
svarog

J'ai trouvé que cette solution fonctionnait parfaitement pour moi. Ne nécessite aucun apis tiers

'test' est en fait un dossier contenant beaucoup de fichiers.

String folderPath= "C:\Users\Desktop\test";
String zipPath = "C:\Users\Desktop\test1.Zip";

private boolean zipDirectory(String folderPath, String zipPath) throws IOException{

        byte[] buffer = new byte[1024];
        FileInputStream fis = null;
        ZipOutputStream zos = null;

        try{
            zos = new ZipOutputStream(new FileOutputStream(zipPath));
            updateSourceFolder(new File(folderPath));

            if (sourceFolder == null) {
                zos.close();
                return false;
            }
            generateFileAndFolderList(new File(folderPath));

            for (String unzippedFile: fileList) {
                System.out.println(sourceFolder + unzippedFile);

                ZipEntry entry = new ZipEntry(unzippedFile);
                zos.putNextEntry(entry);

                if ((unzippedFile.substring(unzippedFile.length()-1)).equals(File.separator))
                    continue;
                try{
                    fis = new FileInputStream(sourceFolder + unzippedFile);
                    int len=0;
                    while ((len = fis.read(buffer))>0) {
                        zos.write(buffer,0,len);
                    }
                } catch(IOException e) {
                    return false;
                } finally {
                    if (fis != null)
                        fis.close();
                }
            }
            zos.closeEntry();
        } catch(IOException e) {
            return false;
        } finally {
            zos.close();
            fileList = null;
            sourceFolder = null;
        }
        return true;
    }

    private void generateFileAndFolderList(File node) {
        if (node.isFile()) {
            fileList.add(generateZipEntry(node.getAbsoluteFile().toString()));
        }
        if (node.isDirectory()) {
            String dir = node.getAbsoluteFile().toString();
            fileList.add(dir.substring(sourceFolder.length(), dir.length()) + File.separator);

            String[] subNode = node.list();
            for (String fileOrFolderName : subNode) {
                generateFileAndFolderList(new File(node, fileOrFolderName));
            }
        }
    }

    private void updateSourceFolder(File node) {
        if (node.isFile() || node.isDirectory()) {
            String sf = node.getAbsoluteFile().toString();
            sourceFolder = sf.substring(0, (sf.lastIndexOf("/") > 0 ? sf.lastIndexOf("/") : sf.lastIndexOf("\\")));
            sourceFolder += File.separator;
        } else
            sourceFolder = null;
    }

    private String generateZipEntry(String file) {
        return file.substring(sourceFolder.length(), file.length());
    }
1
user3336194

Cette méthode compresse un dossier et ajoute tous les fichiers et dossiers enfants (y compris les dossiers vides) dans le fichier Zip.

void zipFolder(Path sourceDir, Path targetFile) throws IOException {
    ZipDirectoryVisitor zipVisitor = new ZipDirectoryVisitor(sourceDir);
    Files.walkFileTree(sourceDir, zipVisitor);
    FileOutputStream fos = new FileOutputStream(targetFile.toString());
    ZipOutputStream zos = new ZipOutputStream(fos);
    byte[] buffer = new byte[1024];
    for (ZipEntry entry : zipVisitor.getZipEntries()) {
        zos.putNextEntry(entry);
        Path curFile = Paths.get(sourceDir.getParent().toString(), entry.toString());
        if (!curFile.toFile().isDirectory()) {
            FileInputStream in = new FileInputStream(Paths.get(sourceDir.getParent().toString(), entry.toString()).toString());
            int len;
            while ((len = in.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            in.close();
        }
        zos.closeEntry();
    }
    zos.close();

}

Et voici l'implémentation de ZipDirectoryVisitor:

class ZipDirectoryVisitor extends SimpleFileVisitor<Path> {
    private Path dirToZip;
    private List<ZipEntry> zipEntries; // files and folders inside source folder as Zip entries
    public ZipDirectoryVisitor(Path dirToZip) throws IOException {
        this.dirToZip = dirToZip;
        zipEntries = new ArrayList<>();
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
        // According to Zip standard backslashes
        // should not be used in Zip entries
        String zipFile = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
        ZipEntry entry = new ZipEntry(zipFile);
        zipEntries.add(entry);
        return FileVisitResult.CONTINUE;
    }


    @Override
    public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
        String zipDir = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
        // Zip directory entries should end with a forward slash
        ZipEntry entry = new ZipEntry(zipDir + "/");
        zipEntries.add(entry);
        return FileVisitResult.CONTINUE;
    }


    @Override
    public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException {
        System.err.format("Could not visit file %s while creating a file list from file tree", path);
        return FileVisitResult.TERMINATE;
    }

    public List<ZipEntry> getZipEntries() {
        return zipEntries;
    }
}
1