JAVA DIRECTORY ZIPPING

Come si comprime una cartella, un file, o una struttura ricorsiva di cartelle

Java offre alcune utilità che consentono di comprimere un file in formato ZIP.  Queste utilità sono rese disponibili nel package java.util.zip. Per zippare una cartella, è necessario scandire i suoi file e aggiungerli al flusso zip che stiamo costruendo. Ad esempio, supponiamo di avere una cartella dirPath che vogliamo zippare in un file chiamato zipFileName: per semplicità la cartella contiene solo files e non altre cartelle (se contenesse altre cartelle potremmo zipparle ricorsivamente). Il codice seguente mostra come è possibile zippare tale cartella:

public class ZipDir {
 
       public static void zipDirectory(File dirPath, String zipFileName)
                                                    throws IOException {
             if(dirPath.exists()) {
                     ZipOutputStream zos = new ZipOutputStream(
                                      new FileOutputStream(zipFileName));
                     zip(dirPath, zos);
                     zos.close();
             }
       }
 
       private static final void zip(File dirPath, ZipOutputStream zos)
                                                    throws IOException {
             File[] files = dirPath.listFiles();
             byte[] buffer = new byte[8192];
             int read = 0;
             for (int i = 0 ; i < files.length; i++) {
                    FileInputStream in = new FileInputStream(files[i]);
                    ZipEntry entry = new ZipEntry(files[i].getPath().substring
                                            (dirPath.getPath().length() + 1));
                    zos.putNextEntry(entry);
                    while (-1 != (read = in.read(buffer))) {
                           zos.write(buffer, 0, read);
                    }
                    in.close();
             }
       }
}
 

Il punto d’ingresso è il metodo zipDirectory, che prende in input il java.io.File della cartella e il nome del file zip risultato. Il metodo zip si occupa di scandire tutti i files contenuti nella cartella, aggiungendoli allo ZipOutputStream come ZipEntry.

Vediamo invece il codice (leggermente pi`u complesso) che consente di comprimere una directory con tutte le sue sotto-directories e files:


public void zipDir(File directory, File zipfile) throws IOException {
	URI base = directory.toURI();
	Deque<File> queue = new LinkedList<File>();
	queue.push(directory);
	OutputStream out = new FileOutputStream(zipfile);
	Closeable res = out;
	try {
	ZipOutputStream zout = new ZipOutputStream(out);
	res = zout;
	while (!queue.isEmpty()) {
		directory = queue.pop();
		for (File kid : directory.listFiles()) {
		  String name = base.relativize(kid.toURI()).getPath();
		  if (kid.isDirectory()) {
		    queue.push(kid);
			name = name.endsWith("/") ? name : name + "/";
			zout.putNextEntry(new ZipEntry(name));
		  } else {
			zout.putNextEntry(new ZipEntry(name));
			copy(kid, zout);
			zout.closeEntry();
		  }
		}
	}
	} finally {
		res.close();
	}
}

private void copy(InputStream in, OutputStream out) throws IOException {
	byte[] buffer = new byte[1024];
	while (true) {
		int readCount = in.read(buffer);
		if (readCount < 0) {
			break;
		}
			out.write(buffer, 0, readCount);
	}
}

private void copy(File file, OutputStream out) throws IOException {
	InputStream in = new FileInputStream(file);
	try {
		copy(in, out);
	} finally {
		in.close();
	}
}