Collections


Comment compresser un répertoire dans un fichier zip ?

Lire le contenu d'un répertoire

Un répertoire, comme un fichier, est représenté par une instance de java.io.File. On peut parcourir l'ensemble de ses fichiers avec la méthode listFiles.

 File directory = new File(...);
 File[] allFiles = directory.listFiles();
   for (File file : allFiles) {
     //...
   }

Pour lire le contenu d'un fichier, on utilise un FileInputStream, puis on lit chaque byte par byte ou, pour optimiser, par paquets de bytes.

     FileInputStream inputStream = new FileInputStream(file);
     int data;
     while ((data = inputStream.read()) >= 0) {
       //...
     }

Ecrire un fichier Zip

Pour écrire un fichier Zip, il faut assembler un FileOutputStream à un ZipOutputStream.

 File zipFile = new File(directory.getName() + ".zip");
 FileOutputStream fOut = new FileOutputStream(zipFile);
 ZipOutputStream zOut = new ZipOutputStream(fOut);

Pour chaque fichier, on doit créer une entrée du fichier zip, avant d'écrire des bytes, puis de fermer l'entrée.

   // Déclaration de la première entrée de l'archive
   zOut.putNextEntry(new ZipEntry(file.getName()));
   int data;
   while ((data = inputStream.read()) >= 0) {
     zOut.write(data);
   }
   zOut.closeEntry();

Exemple complet

Si on assemble tout ces éléments, on peut faire fonctionner cet exemple, pour un répertoire à 1 seul niveau de profondeur.

 package fr.sewatech.formation.io;
 
 import java.io.*;
 import java.util.zip.*;
 
 public class ZipDirExample {
   public static void main(String[] args) {
     System.out.println(writeZip(new File("nio")));
   }
   
   public static File writeZip(File directory) {
     // Si ce n'est pas un répertoire...
     if (!directory.isDirectory()) {
       return null;
     }  
     
     FileOutputStream fOut = null;
     ZipOutputStream zOut = null;
     try {
       // Déclaration de l'archive ZIP
       File zipFile = new File(directory.getName() + ".zip");
       fOut = new FileOutputStream(zipFile);
       zOut = new ZipOutputStream(fOut);
       
       File[] allFiles = directory.listFiles();
       for (File file : allFiles) {
         if (file.isFile()) {
           // Flux de lecture du fichier
           FileInputStream inputStream = new FileInputStream(file);
           
           // Déclaration de la première entrée de l'archive
           zOut.putNextEntry(new ZipEntry(file.getName()));
           int data;
           while ((data = inputStream.read()) >= 0) {
             zOut.write(data);
           }
           zOut.closeEntry();
         }
       }
       return zipFile;
     } catch (Exception e) {
       throw new SwException(e);
     } finally {
       try {
         if (zOut != null) {
           zOut.close();
         }
       } catch (IOException e) {
       }
     }
   }
 }

Conclusion

Avec un peu de récursivité, on peut traiter le cas d'un répertoire contenant d'autres répertoires...