ePrometeusCorsoJavaJava
testi articoli
Testi Articoli  Download
Home | Eshop | Java | Tools | Web | 
CorsoJava è ora Video! Free for all!
Clicca Qui!

GENERARE ZIP IN JAVA
Gestione degli Zip col JDK 1.1
Creare uno zip
La classe jzip.JZip
L'Autore

<<< Gestione degli Zip col JDK 1.1 >>>

Michele Sciabarrà

Il JDK supporta il formato JAR di archiviazione dei programmi in Java, che sono in realtà in formato ZIP. Niente di strano quindi che internamente sia presente il supporto per i file ZIP. Saggiamente quindi JavaSoft ha deciso di rendere disponibili delle classi per l'uso generale del formato zip. Da notare che gli zip non sono interamente gestiti in Java. Infatti tra le DLL del JRE (Java Runtime Environment) esiste una zip.dll che chiaramente implementa in C le chiamate native necessarie per la gestione degli ZIP. Si tratta, con tutta probabilità, di codice derivato dalla versione freeware dello zip nota come Info-Zip. In realtà il supporto al formato ZIP non è completo. Lo ZIP prevede diversi metodi di compressione, mentre è previsto il solo supporto per la compressione deflating, che ha 9 livelli diversi di compressione, e per lo storing senza compressione. Altresì è previsto il supporto per la pura compressione deflating senza archiviazione ZIP, il formato utilizzato dalla famora utility gzip, che come è noto non è un archiviatore ma solo un compressore. Si tratta comunque di tutto e solo quello che è necessario in pratica: le altre forme di compressione dello ZIP sono un residuo storico del PKZIP 1.0, mentre il deflating è la compressione introdotta nel PKZIP 2.0 che è la più efficiente in pratica. I livelli di compressione, più alti sono più è efficiente la compressione, ma è anche più lenta. In questo articolo metteremo alla prova la gestione degli zip e ne impararemo l'uso, implementando una piccola utility a linea di comando, jzip, che permette di listare, scompattare e creare degli zip. La sintassi dell'utility (che ricorda quella del comando tar ) è:

java jzip.JZip -t &ltfilename.zip>
show zip contents
java jzip.JZip -x &ltfilename.zip>
extract files
java jzip.JZip -c &ltfilename.zip> &ltfiles>...
create a zip with files

Tralasciamo di discutere i dettagli (piuttosto ovvi) relativi alla gestione della riga di comando e concentriamoci nell'analisi dei tre metodi principali della classe jzip.Jzip che sono:

void list(String filename)
void unzip(String filename)
void zip(String filename, String[] files)
Listare uno zip

In questo paragrafo faremo riferimento a JZip.list. Per accedere ad un file zip si utilizza la classe ZipFile; uno zip è un archivio, e contiene al suo interno altri file. Ogni file contenuto è rappresentato dalla classe ZipEntry. Un oggetto ZipFile può essere costruito specificando un file per nome (una stringa) o un oggetto di tipo File. In JZip.list uno ZipFile viene costruito usando come argomento il nome del file specificato sulla riga di comando. Tramite ZipFile.entries(), ottenieamo una enumerazione delle ZipEntry contenute nel file. La classe ZipEntry fornisce i metodi per estrarre le informazioni sui file contenuti nello zip. Quindi per listare i contenuti la nostra utility deve enumerare le entry; per ciascuna deve leggere le informazioni e stampare il risultato. Ci sono alcuni dettagli a cui dobbiamo stare attenti.

Notiamo innanzitutto l'uso del SimpleDateFormat per stampare la data. Infatti ZipEntry.getSize() fornisce la data in secondi dal primo gennaio 1970, che deve essere convertito in una stringa con l'uso dell'apposito formattatore di date. Un altro trucco è quello utilizzato per allineare a destra un numero, cioè la lunghezza del file in byte: abbiamo aggiunto degli spazi in testa ed estratto la sottostringa di coda. Notiamo infine come, listando i file contenuti in uno zip, i file hanno sempre il pathname separato da slash diritti anche se sono stati originariamente creati in ambiente Windows. Questa caratteristica degli ha delle conseguenza a cui dobbiamo fare attenzione quando tentiamo di scompattare. Scompattare uno zip

La procedura di scompattamento assomiglia al listing nella parte relativa all'estrazione delle entry. Per ciascuna entry dobbiamo però dearchiviare il file zip anzichè esaminare e stampare la entry. Un fle viene estratto utilizzando un output stream, fornito dalla classe ZipFile specificando la entry. Cioè se zip è uno ZipFile e entry è una ZipEntry corrispondente al file che vogliamo estrarre, otteniamo l'input stream in con:

InputStream in = zip.getInputStream(entry);

Una volta ottenuto l'input stream, possiamo leggerlo e scriverlo in un file.

Per creare e scrivere un file possiamo utilizzare un FileOutputStream: in teoria basterebbe

OutputStream out =
        new FileOutputStream(entry.getName())

però questo codice non funziona per due motivi. Il primo è che gli slash sono sempre diritti, mentre sotto Windows devono essere inversi. Il secondo è che la directory in cui si vuole scrivere il file deve già esistere, cosa che in generale non è vera. Per ovviare a questi problemi, per prima cosa "naturalizziamo" il nome del file, trasformando gli slash nel

ZipEntry entry = (ZipEntry)e.nextElement();
StringBuffer fixed = new StringBuffer(entry.getName());
for( int i = 0; i&ltfixed.length(); ++i)
     if( fixed.charAt(i) == '/')
         fixed.setCharAt(i, File.separatorChar);

Fatto questo creiamo la directory dove si trova il file sfruttando File.mkdirs, e ovviamente non creando alcun file se l'entry è relativa ad una directory.

File file = new File(fixed.toString());
if(entry.isDirectory()) {        
 file.mkdirs();
         continue; // non bisogna creare file
} else {      
  String dir = file.getParent();
  if( dir != null)
   new File(dir).mkdirs();
}
A questo punto non ci resta che estrarre il file:
System.out.println("unzipping: "+file);
OutputStream out = new FileOutputStream(file);
InputStream in = zip.getInputStream(entry);
while( (n = in.read(buff, 0, buff.length))!= -1)
        out.write(buff, 0 , n);
    }
  }
ePrometeus s.r.l. - Web Software House & Open Source System Integrator
MILANO - SAN BENEDETTO DEL TRONTO(AP)
Contatti: info@eprometeus.com