Newsgroup: it.comp.java
Titolo: Oggetto zippante.

Ciao,
    se a qualcuno interessa ho creato una classe in grado di mantenere al suo interno un
qualsiasi oggetto serializzabile in forma compressa, cosa che risulta molto utile nel caso
in cui dobbiate spedire questo oggetto serializzandolo su per qualche rete lenta.
    Il funzionamento e' molto semplice, e potete anche provarlo subito con il main()
provvisto con la classe: in pratica esiste un costruttore unico che riceve in ingresso un
object, (e che lo zippa)  e un API getValue() che ritorna l'oggetto stesso (unzippandolo).
Esistono inoltre un paio di API accessorie (e vabbe', guardatevele!) e un API statica che
imita la mitica sizeof del C. Se avete qualche dubbio o qualche consiglio intelligente e/o
migliorativo fatemi sapere! (come algoritmo ho usato il GZIP, + veloce ed in generale con
il miglior rapporto qualita'/ prezzo!)
Bruno.
---------------- ZippedObject.java ---------------------------
import java.io.*;
import java.util.zip.*;
/**
 * Mantiene una versione compressa di un oggetto:
 * utile per serializzarlo su reti lente
 *
 * @author 	Bruno Bossola
 * @version	1.0
 *
 * P.S. Hey, se potete non cambiate il nome dell'autore!
 */
public class ZippedObject implements Serializable
{
    // i dati dell'oggetto zippato
    private byte[] data;
    // il tempo elapsed dell'ultima operazione di zip / unzip
    private transient long elapsed;
    // l'oggetto da zippare
    private transient Object value;
    /**
     * Crea un nuovo oggetto contenente
     * la versione zippata di un oggetto
     *
     * @param obj   oggetto da comprimere
     */
    public ZippedObject(Object obj)
    {
        long t = System.currentTimeMillis();
        try
        {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            GZIPOutputStream zos = new GZIPOutputStream(bos);
            ObjectOutputStream oos = new ObjectOutputStream(zos);
            oos.writeObject(obj);
            oos.close();
            data = bos.toByteArray();
        }
        catch (Exception ex)
        {
            if (DEBUG) ex.printStackTrace();
            throw new OutOfMemoryError("Unable to perform operation");
        }
        elapsed = System.currentTimeMillis()-t;
    }
    /**
     * Ritorna la versione originale
     * dell'oggetto zippato
     *
     * @return  oggetto originale
     */
    public Object getValue()
    {
        if (value == null)
        {
            long t = System.currentTimeMillis();
            try
            {
                ByteArrayInputStream bis = new ByteArrayInputStream(data);
                GZIPInputStream zis = new GZIPInputStream(bis);
                ObjectInputStream ois = new ObjectInputStream(zis);
                value = (Serializable)ois.readObject();
                ois.close();
            }
            catch (Exception ex)
            {
                if (DEBUG) ex.printStackTrace();
                throw new OutOfMemoryError("Unable to perform operation");
            }
            elapsed = System.currentTimeMillis()-t;
        }
 
        return value;
    }
    /**
     * Ritorna il tempo elapsed dell'ultima operazione di zip / unzip.
     * Questo metodo e' mappato su una variabile trasiente, pertanto
     * perde di significato allorche' l'oggetto venga serializzato
     *
     * @return  elapsed in millisec. ultima operazione zip / unzip
     */
    public long getElapsed()
    {
        return elapsed;
    }
    /**
     * Ritorna la dimensione della versione compressa dell'oggetto
     *
     * @return  dimensione compressa oggetto
     */
    public int getCompressedSize()
    {
        return data.length;
    }
    /**
     * Funzione di utilita' che calcola la
     * dimensione in bytes di un oggetto
     */
    public static int sizeOf(Object obj)
    {
        int res=0;
        try
        {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.close();
            res = bos.toByteArray().length;
        }
        catch (Exception ex)
        {
            if (DEBUG) ex.printStackTrace();
            throw new OutOfMemoryError("Unable to perform operation");
        }
        return res;
    }
    /**
     * main() interno di test
     */
    public static void main(String args[])
    {
	if (DEBUG)
	{
            // crea l'oggetto di test
            int rows = 500, cols = 20;
            String[][] data = new String[rows][];
            for (int r=0; r<rows; r++)
            {
                data[r] = new String[cols];
                for (int c=0; c<cols; c++)
                    data[r][c] = "data - "+r+" - "+c+" - "+(r*c);  //Math.random();
            }
            // zippa / unzippa l'opggetto mostrando statistiche
            System.out.println("\nZipping...");
            ZippedObject zo = new ZippedObject(data);
            System.out.println("Elapsed time:        "+zo.elapsed);
            System.out.println("Original data size:  "+ZippedObject.sizeOf(data));
            System.out.println("Zipped data size:    "+zo.data.length);
            System.out.println("\nUnzipping...");
	    String[][] res = (String[][])zo.getValue();
            System.out.println("Elapsed time:        "+zo.elapsed);
        }
    }
    // flag interno di debug
    private static final boolean DEBUG = true;
}
|
| Bruno Bossola
| A Java Software Engineer :-)
|

 in cui dobbiate spedire questo oggetto serializzandolo su per qualche rete lenta.
Vedo che c'è convergenza... anche io ho dovuto spedire oggetti serializzati zippati, solo che
ho usato un approccio un po' diverso, zippando direttamente lo stream fra applet e servlet, e
facendo in modo che la servlet potesse riconoscer streame non zippati (non è detto che sia
conveniente zippare tutto).
ciao
--
Ugo
__________________________________________________________________________
"La perfezione si ottiene non quando non c'è nient'altro da aggiungere,
 bensì quando non c'è più niente da togliere." Antoine de Saint-Exupéry
__________________________________________________________________________
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enterprise Java Consulting
@mail: Ugo.L...@Flashnet.it
Home Page: 
http://www.ugolandini.net
Mentoring: 
http://www.projectoo.com
Work Phone: 02/61860647-6-4 06/58332267
Cell Phone: 0347/6310749 - 0347/4783580
Fax Phone: 02/700 413 187
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Diciamo che io ho scelto di zippare gli oggetti perche' il design dell'applicazione si
adattava molto bene a questo,.. In pratica io zippo il risultato di query, e solo quando
risulta necessario, in dipendenza dal numero di righe lette. Effettivamente non sempre e'
premiante zippare (specialmente se i dati sono pochi) come comunque mi sembra faccia anche
tu... vedo che c'e' convergenza :-)
Ciao,
    Bruno.
