Compressione Zip
Molte sorgenti di informazioni contengono dati ridondanti che appesantiscono le comunicazioni fra Client e Server ed in generale fra diversi computer.In questo senso la compressione svolge una funzione molto importante perché a fronte di un piccolo costo di tempo (necessario a comprimere i dati all’origine e a decomprimerli alla sorgente) permette di eliminare tali ridondanze risparmiando risorse di memoria e/o di banda.
Generalmente l’approccio alla compressione di dati può avvenire:
- via software mediante l’applicazione di determinati algoritmi (si pensi ad esempio alla codifica di Huffman)
- via hardware mediante un circuito dedicato allo svolgimenti di tali operazioni
 
                
                    Compressione e decompressione
                  
La operazioni di compressione e decompressione sono l’una l’inverso dell’altra e pertanto sono rappresentabili mediante una black-box bidirezionale.
                - lossy che comportano una perdita di dati e quindi una diminuzione della qualità delle informazioni (si pensi ad esempio al formato jpg per le immagini)
- lossless che comprimono i dati senza alcuna perdita e quindi il flusso di informazioni può essere completamente ricostruito
- zip che supporta diversi algoritmi di compressione e sebbene altri formati offrano rapporti di compressione maggiori la sua diffusione gli permette di essere uno dei formati per compressione dati più diffusi
- gzip GNU Zip che fu inizialmente creato da Jean-loup Gailly and Mark Adler ed usa l’algoritmo di Lempel-Ziv
Decompressione dei dati
Per decomprimere un file zip è possibile agire in due distinti modi:- accedendo sequenzialmente a tutti i file compressi all’interno dell’archivio zip
- accedendo in maniera casuale ai file compressi all’interno dell’archivio zip
Accesso sequenziale ai file
L’accesso sequenziale ai file compressi all’interno di un archivio zip e la loro conseguente estrazione si avvale della classe ZipInputStream.Tale classe infatti mediante il metodo getNextEntry() permette di recuperare i punti di accesso dei vari file memorizzati all’interno dell’archivio sottoforma di ZipEntry.
Un oggetto ZipEntry memorizza informazioni relative:
- al nome del file compresso getName()
- alla dimensione del file compresso getCompressedSize()
- al commento associato getComment()
- al metodo di compressione utilizzato getMethod()
- alla dimensione del file non compresso getSize()
- creare uno ZipInputStream associato al file zip da decomprimere 
                   
                   
                  
                  FileInputStream fis = new FileInputStream("filezip.zip"); ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));
- identificare i punti di accesso ZipEntry dei vari file memorizzati all’interno ed avviarne l’estrazione
                  ZipEntry entry; while((entry = zin.getNextEntry()) != null) { ... }
try
{
   BufferedOutputStream output = null;
   FileInputStream fis = new FileInputStream("filezip.zip");
   ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
   ZipEntry entry;
   while((entry = zis.getNextEntry()) != null)
   {
      int count;
      byte dati[] = new byte[1024];
      FileOutputStream fos = new FileOutputStream(entry.getName());
      output = new BufferedOutputStream(fos, 1024);
      while ((count = zis.read(dati, 0, 1024))!= -1)
      {
         output.write(dati, 0, count);
      }
      output.flush();
      output.close();
   }
   zis.close();
}
catch(Exception e)
{
   ...
}
              Accesso casuale ai file
Per accedere direttamente ai file compressi all’interno di un archivio zip è possibile ricorrere alla classe ZipFile che è appunto rappresentativa di un archivio zip.La classe ZipFile contiene fra gli altri i metodi:
- getEntry(String name) che permette di recuperare lo ZipEntry relative ad un determinato file (specificato dal nome passato come parametro)
- entries() che restituisce sotto forma di un oggetto Enumeration tutti gli ZipEntry dei file memorizzati all’interno dell’archivio zip
...
ZipFile zipfile = new ZipFile("filezip.zip");
Enumeration e = zipfile.entries();
ZipEntry entry = (ZipEntry) zipfile.getEntry("miofile");
BufferedInputStream is = new BufferedInputStream(zipfile.getInputStream(entry));
...
              Compressione dei dati
Analogamente a quanto visto per la decompressione di archivi, la compressione di file in formato zip si avvale della classe ZipOutputStream che permette di ottenere l’OutputStream del file sul quale vogliamo scrivere i nostri dati compressi.
FileOutputStream output = new FileOutputStream("filezip.zip");
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(output));
Ottenuto l’oggetto ZipOutputStream occorre aprire un InputStream relativo alla sorgente di dati che vogliamo comprimere:
              FileInputStream fi = new FileInputStream(miofile); Creare uno ZipEntry per il file in questione: ZipEntry entry = new ZipEntry(miofile));e registrarlo all’interno del flusso di output sfruttando il metodo putNextEntry(ZipEntry e):
out.putNextEntry(entry);ed infine procedere al salvataggio dei dati mediante la lettura dalla sorgente di input ed il salvataggio nel file di destinazione.
Ecco un esempio completo:
BufferedInputStream input = null;
FileOutputStream output = new FileOutputStream("filezip.zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(output));
out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[1024];
File f = new File(miofile);
FileInputStream fi = new FileInputStream(miofile);
input = new BufferedInputStream(fi, 1024);
ZipEntry entry = new ZipEntry(miofile);
out.putNextEntry(entry);
int count;
while((count = input.read(data, 0, 1024)) != -1)
{
   out.write(data, 0, count);
}
input.close();
out.close();
              Checksum
Molto spesso nelle comunicazioni Client-Server si verificano degli errori di comunicazione: l’interfaccia Checksum (e le sue implementazioni concrete Adler32 e CRC32) definisce appunto una somma di controllo per identificare eventuali errori di trasmissione o di corruzione di file presenti all’interno di un archivio zip.
                  Tipicamente la Checksum viene aggiunta al flusso di dati e ricalcolata alla sorgente: se le due checksum sono diverse allora i dati ricevuti sono corrotti altrimenti i dati ricevuti non hanno subito errori.
                
              ... CheckedOutputStream checksum =new CheckedOutputStream(dest, new Adler32()); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum)); ...Analogamente per creare uno ZipInputStream è possibile scrivere:
... CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32()); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum)); ...Per recuperare la Checksum da un flusso dati è possibile utilizzare il metodo getChecksum() delle classi CheckedOutputStream e CheckedInputStream.
                    Compressing and Decompressing Data using Java
Tutorial sul sito della Sun sulla compressione e decompressione in Java.
                  Tutorial sul sito della Sun sulla compressione e decompressione in Java.
                    Documentazione java.util.zip
Documentazione sul package java.util.zip contenente le classi per la compressione e decompressione zip.
                Documentazione sul package java.util.zip contenente le classi per la compressione e decompressione zip.



 stampa
stampa
              
