You are on page 1of 15

Compresin y descompresin de datos utilizando Java

Compresin y descompresin de datos utilizando Java


Autor: Qusay H. Mahmoud/Konstantin Kladko Traduccin/Adaptacin: RuGI URL Original:http://developer.java.sun.com/developer/technicalArticles/Programming/compressio n/ Muchas fuentes de informacin contienen datos redundantes o datos que no son muy revelantes para la informacin que se quiere guardar. Esto produce grandes cantidades de datos que se transfieren entre el cliente y el servidor de aplicaciones o entre computadoras en general. La solucin obvia a estos problemas de almacenamiento de los datos y traslado de la informacin es instalar dispositivos del almacenamiento adicionales y extender los medios de comunicacin existentes. Hacer esto, sin embargo, requiere un incremento en los costos de operacin en una organizacin. Un mtodo para reducir una porcin el almacenamiento de los datos y la tranferencia de la informacin es a travs de representaciones de los datos con un codigo mas eficiente. Este artculo presenta una ligera introduccin a la compresion y descompresion de datos, y muestra cmo comprimir y descomprimir estos, eficaz y convenientemente, desde tus aplicaciones Java usando el paquete java.util.zip Mientras qu es posible comprimir y descomprimir datos usando herramientas como WinZip, gzip, y JAR, stas se usan como aplicaciones aisladas. Es posible invocar estas herramientas desde tus aplicaciones Java, pero sta no es un manera correcta de utilizarlas y no es una solucin eficaz. Este artculo:

Muestra brevemente las generalidades de la compresin de datos Describe el paquete java.util.zip Muestra cmo usar este paquete para comprimir y descomprimir datos Muestras cmo comprimir y descomprimir objetos serializados para ahorrar espacio en disco Muestras cmo comprimir y descomprimir datos al vuelo (antes de transmitir) para mejorar el desempeo de aplicaciones cliente/servidor

Generalidades de la compresin de datos


Un ejemplo sencillo de redundancia de datos en un archivo es la repeticin de caracteres. Por ejemplo, considera la siguiente cadena:
BBBBHHDDXXXXKKKKWWZZZZ

Este cadena puede ser codificada y compactada reemplazando cada subcadena repetida de carcteres por un solo carcter repetido y un nmero que representa el nmero de veces que el carcter se repite. La cadena anterior puede codificarse as:
4B2H2D4X4K2W4Z

http://www.javahispano.com

Aqui, "4B" significa cuatro B's, "2H" significa dos H's, y asi sucesivamente. La compresin de cadenas con este algoritmo se conoce somo RLE (run-length encoding) Como otro ejemplo, considera el almacenamiento de una imagen rectangular. Como una sencilla imagen de un mapa de bits, sta se puede almacenar como muestra la Figura 1. 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000111111111111111111110000000000 0000000000100000000000000000010000000000 0000000000100000000000000000010000000000 0000000000100000000000000000010000000000 0000000000111111111111111111110000000000 0000000000000000000000000000000000000000
Fig.1. Un mapa de bits con informacin para el RLE

Otro manera podra ser guardar la imagen como un metafile grfico:


Rectangle 11, 3, 20, 5

Que significa; el rectngulo comienza en la coordenada (11,3) y tiene 20 pixeles de ancho y 5 de alto. La imagen rectangular puede comprimirse utilizando RLE a travs del conteo de bits identicos, as:
0, 40 0, 40 0,10 1,20 0,10 0,10 1,1 0,18 1,1 0,10 0,10 1,1 0,18 1,1 0,10 0,10 1,1 0,18 1,1 0,10 0,10 1,20 0,10 0,40

La primera lnea nos dice que la primera lnea del mapa de bit's consiste en 40 0's. La tercera lnea dice que la tercera lnea del mapa de bit's consiste en 10 0's seguidos por 20 1's y seguidos por 10 0's ms, y as sucesivamente para las otras lneas. Nota que RLE requiere representaciones diferentes para el archivo y su versin codificada, dependiendo del tipo del archivo. Por consiguiente, este mtodo no puede trabajar con todos los tipos de archivos. Otras tcnicas de compresion incluyen variaciones de RLE, una es VLE variable-length encoding (tambin conocida como cdigo Huffman ), y muchas otros. Para ms informacin, hay muchos libros disponible sobre tcnicas de compresion de datos imagenes. Hay muchos beneficios con la compresin de los datos. No obtante, la ventaja principal es reducir requisitos de almacenamiento. Tambin, para comunicaciones de los datos, la transferencia de datos comprimidos aumenta la cantidad de informacin transmitida. Observa que la compresin de datos puede implementarse con el hardware ya existente, con software o usando dispositivos de hardware especiales que ya incorporn las tcnicas de compresin. La Figura 2 muestra un diagrama de bloques basico sobre la compresin de datos.
2

Compresin y descompresin de datos utilizando Java

_________________ ----------------------> Compresion ----------------------> Datos Originales de Datos comprimidos <--------------------datos <--------------------_________________

Fig.2. Diagrama de Bloques. Compresin de datos

ZIP vs GZIP
Si ests trabajando con Windows, podras estar familiarizado con la herramienta WinZip que se utiliza para crear un archivo comprimido y para extraer archivos de un archivo comprimido. En UNIX, sin embargo, las cosas se hace de forma ligeramente distinta. El comando tar se usa para crear un archivo (no comprimido) y otro programa (gzip o compress) se usa para comprimir el archivo.

El paquete java.util.zip
Java proporciona el paquete java.util.zip para trabajar con archivos compatibles con el formato zip. este paquete proporciona clases que te permiten leer, crear, y modificar archivos con los formatos ZIP y GZIP. Tambin te proporciona clases para comprobar las sumas de control de flujos de entrada y puede ser usado para validar entradas de datos. Este paquete proporciona una interface, catorce clases, y dos clases de excepciones como se muestra en la Tabla 1.
Tabla 1. El paquete java.util.zip

Elemento
Checksum

Tipo Interface Clase Clase Clase Clase Clase Clase Clase Clase

Descripcin Representa un dato de la suma de control (data checksum). Implementado por las clases Adler32 y
CRC32

Adler32

CheckedInputStream

Usado para calcular la suma de control(checksum) de un flujo de datos Un flujo de entrada que guarda la suma de control de los datos que estan siendo ledos. Un flujo de salida que guarda la suma de control de los datos que estan siendo escritos. Usado para calcular la suma de control CRC32 de un flujo de datos Soporte para compresion usando la librera ZLIB Un flujo de salida filtrado para la compresin de datos con el formato de compresin deflate Un flujo de entrada filtrado para leer datos comprimidos con el formtato GZIP Un flujo de salida filtrado para escribir datos comprimidos con el formato GZIP
3

CheckedOutputStream CRC32 Deflater DeflaterOutputStream

GZIPInputStream

GZIPOutputStream

http://www.javahispano.com

Inflater InflaterInputStream ZipEntry ZipFile ZipInputStream ZipOutputStream

Clase Clase Clase Clase Clase Clase Clase de excepcion Clase de exepcion

Soporte para descompresion usando la librera ZLIB Un flujo de entrada filtrado para la descompresion de datos con el formato de compresin deflate Representa la entrada de un archivo ZIP Usado para leer entradas de un archivo ZIP Un filtro de entrada para leer archivos con el formato
ZIP

Un filtro de salida para escribir archivos con el formato ZIP Lanza una excepcin para sealar un error en el formato de los datos Lanza una excepcin para sealar un error en el formato Zip

DataFormatException ZipException

Nota: La librera de compresin ZLIB se desarroll inicialmente como parte de la norma PNG(Portable Network Graphics) que no esta protegida por patentes.

Comprimiendo y descomprimiendo datos desde un archivo ZIP


El paquete java.util.zip proporciona clases para la compresin y descompresin de datos. La descompresin de un archivo ZIP es solo la lectura de datos desde un flujo de entrada. El paquete java.util.zip proporciona la clase ZipInputStream para leer archivos ZIP. Un ZipInputStream se crea como cualquier otro flujo de entrada. Por ejemplo, el siguiente fragmento de cdigo se usa para crear un flujo de entrada para leer datos de un archivo con formato ZIP:
FileInputStream fis = new FileInputStream("figs.zip"); ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));

Una vez creado el flujo de entrada ZIP, puedes leer las entradas del archivo ZIP usando el mtodo getNextEntry que retorna un objeto ZipEntry. Si se alcanza el fin del archivo(EOF) getNextEntry retorna null:
ZipEntry entry; while((entry = zin.getNextEntry()) != null) { // extraer los datos // abrir flujos de salida }

Ahora, es momento de preparar un flujo de salida descomprimido, esto se puede hacer de la siguiente manera:
int BUFFER = 2048; 4

Compresin y descompresin de datos utilizando Java

FileOutputStream fos = new FileOutputStream(entry.getName()); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);

Nota: En el cdigo anterior se uso BufferedOutputStream en lugar de ZIPOutputStream. ZipOutputSream y GZIPOutputStream usan un buffer interno de 512 bytes. El uso de BufferedOutputStream es justificado nicamente cuando el tamao del buffer a utilizar es mucho mas grande que 512 bytes (en este ejemplo 2048). Mientras que ZipOutputSream no te permite modificar el tamao del buffer, GZIPOutputStream si lo hace; puedes especificar el tamao del buffer interno como un argumento de su constructor.

En este segmento de cdigo, un flujo de salida de archivo se crea usando el nombre de la(s) entrada(s) ZIP que puede recuperarse usando el mtodo entry.getName. La fuente de datos ZIP es entonces leida y se escribe en un flujo descomprimido:
while ((count = zin.read(data, 0, BUFFER)) != -1) { //System.out.write(x); dest.write(data, 0, count); }

y finalmente, cerramos los flujos de entrada y salida:


dest.flush(); dest.close(); zin.close();

El codigo del Ejemplo 1 muestra como descomprimir y extraer archivos desde un archivo ZIP. Para probar este ejemplo, compila y ejecuta el ejemplo pasndole como parmetro un archivo comprimido con el formato ZIP:
prompt> java UnZip somefile.zip

Nota que somefile.zip debe ser un archivo creado usando alguna herramienta compatible con el formato ZIP, como WINZIP. Ejemplo 1: UnZip.java
import java.io.*; import java.util.zip.*; public class UnZip { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedOutputStream dest = null; FileInputStream fis = new FileInputStream(argv[0]); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); ZipEntry entry; 5

http://www.javahispano.com

while((entry = zis.getNextEntry()) != null) { System.out.println("Extracting: " +entry); int count; byte data[] = new byte[BUFFER]; // Escribir los archivos en el disco FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = zis.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); } zis.close(); } catch(Exception e) { e.printStackTrace(); } } }

Es importante hacer notar que la clase ZipInputStream lee archivos ZIP secuencialmente. La clase ZipFile, en cambio, lee el contenido de un archivo ZIP usando un acceso aleatorio interno para que las entradas del archivo ZIP no tengan que ser ledas secuencialmente

Nota: Otra diferencia fundamental entre ZipInputSream y ZipFile s en terminos del uso de la memoria de intercambio(chach). Las entradas ZIP no son puestas en la memoria de intercambio cuando el archivo es leido usando una combinacin de ZipInputStream y FileInputStream. Por otro lado, si el archivo es abierto usando ZipFile(fileName) entonces es colocado en la memoria intermedia, as si ZipFile(fileName) es llamado otra vez el archivo slo se abre una vez. Si trabajas sobre UNIX, cabe mencionar que todos los archivos ZIP abiertos usando ZipFile son abiertos utilizando memoria mapeada, y por consiguiente el desempeo de ZipFile es superior a ZipInputStream. Por otro lado, si los contenidos del mismo ZIP, son frecuentemente modificados y recargados durante la ejecucin del programa entonces se recomienda el uso de ZipInputStream

A continuacion se muestra como se puede descomprimir un archivo ZIP utilizando la clase ZipFile: 1. Crear un objeto ZipFile especificando el archivo ZIP a ser leido, ya sea como un String o como un objeto File:
ZipFile zipfile = new ZipFile("figs.zip");

Compresin y descompresin de datos utilizando Java

2. Usa el mtodo entries, que retorna un objeto Enumeration, despus con un ciclo obten todos los objetos ZipEntry del archivo a descomprimir:
3. while(e.hasMoreElements()) { 4. entry = (ZipEntry) e.nextElement(); 5. // lee el contenido y guardalo 6. }

7. Lee el contenido de un objeto ZipEntry en especifico dentro del archivo ZIP pasando el objeto ZipEntry al mtodo getInputStream, que retornar un objeto InputStream desde el cual puedes leer el contenido de las entradas:
8. is = new 9. BufferedInputStream(zipfile.getInputStream(entry));

10. Recupera el nombre de la entrada y crea un flujo de salida para guardarlo:


11. 12. 13. 14. 15. 16. 17. byte data[] = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(data, 0, BUFFER)) != -1){ dest.write(data, 0, count); }

18. Finalmente, cierra todos los fujos de entrada y salida:


19. 20. 21. dest.flush(); dest.close(); is.close();

El cdigo completo de este programa se muestra en el ejemplo 2. Nuevamente, para probar esta clase, compilalo y ejecutalo pasandole como argumento un archivo con formato ZIP:
prompt> java UnZip2 somefile.zip

Ejemplo 2: UnZip2.java
import java.io.*; import java.util.*; import java.util.zip.*; public class UnZip2 { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedOutputStream dest = null; BufferedInputStream is = null; ZipEntry entry; ZipFile zipfile = new ZipFile(argv[0]); Enumeration e = zipfile.entries(); while(e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); System.out.println("Extracting: " +entry); is = new BufferedInputStream (zipfile.getInputStream(entry)); int count; byte data[] = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(entry.getName()); 7

http://www.javahispano.com

dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); is.close(); } } catch(Exception e) { e.printStackTrace(); } } }

Comprimiendo y Archivando Datos en un Archivo ZIP


la clase ZipOutputStream se usa para compimir datos a un archivo ZIP. ZipOutputStream escribe datos, en un flujo de salida, en un archivo con formato ZIP. La creacin de un archivo ZIP involucra la siguiente serie de pasos: 1. El primer paso es crear un objeto ZipOutputStream ; le pasaremos como parmetro el flujo de salida del archivo al cual queremos escribir. Aqui se muestra la manera de crear un archivo ZIP llamado "myfigs.zip":
2. 3. 4. 5. FileOutputStream dest = new FileOutputStream("myfigs.zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

6. Una vez que el flujo de salida objetivo es creado, el siguiente paso es abrir el o los archivos origen de los datos. En este ejemplo, los archivos a partir de los cuales se crear el archivo ZIP son aquellos archivos que se escuentren en el directorio actual. El mtodo list se usa en este ejemplo para obtener la lista de los archivos que se encuentran en el directorio actual:
7. 8. 9. 10. 11. 12. 13. 14. File f = new File("."); String files[] = f.list(); for (int i=0; i<files.length; i++) { System.out.println("Adding: "+files[i]); FileInputStream fi = new FileInputStream(files[i]); // creamos una entrada zip // agregamos entradas zip al archivo }

Nota:El cdigo anterior es capaz de comprimir todos los archivos que se encuentran en el directorio actual. No maneja subdirectorios. Como ejercicio, puedes intentar modificar el ejemplo 3 para que maneje subdirectorios

Compresin y descompresin de datos utilizando Java

15. Creamos un ZipEntry por cada archivo leido:


16. ZipEntry entry= new ZipEntry(files[i])

17. Antes de escribir los datos en el flujo ZIP de salida, debes primero colocarle el objeto ZipEntry usando el mtodo putNextEntry:
18. 20. 21. 22. 23. out.putNextEntry(entry); int count; while((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); }

19. Escribimos los datos en el archivo ZIP:

24. Finalmente, cerramos los flujos de entrada y salida:


25. 26. origin.close(); out.close();

El cdigo completo de todo lo anterior se muestra en el ejemplo 3. Ejemplo 3: Zip.java


import java.io.*; import java.util.zip.*; public class Zip{ static final int BUFFER = 2048; public static void main(String argv[]){ try{ BufferedInputSream origin = null; FileOutputStream dest = new FileOutputStream("c:\\temp\\myfigs.zip"); ZipOutputStream out = new ZipOutputStream( new BufferedOutputStream(dest)); //out.setMethod(ZipOutputStream.DEFLATED); byte data[] = new byte[BUFFER]; //obtenemos la lista de los archivos del directorio actual File f = File("."); String files[] = f.list(); for (int i=0; i>files.length; ++i){ System.out.println("Adding: "+file[i]); FileInputStream fi = new FileInputStream(files[i]); origin = new BufferedInputSteam(fi, BUFFER); ZipEntry entry = new ZipEntry(files[i]); out.putNextEntry(entry); int count; while((count = origin.read(data, 0, BUFFER))!= -1){ out.write(data, 0, count); } origin.close(); } out.close(); }catch(Exception e){ e.printStrackTrace(); } } }

http://www.javahispano.com

Nota:Las entradas pueden ser agregadas al archivo ZIP de forma comprimida (DEFLATED) o no comprimida(STORED). El mtodo setMethod se usa para fijar el mtodo de almacenamiento. Por ejemplo, para fijar el mtodo a DEFLATED (comprimido) es: out.setMethod(ZipOutputStream.DEFLATED) y para fijarlo a STORED (no comprimido) es: out.setMethod(ZipOutputStream.DEFLATED)

Propiedades de un Archivo ZIP


La clase ZipEntry describe un archivo comprimido almacenado en un archivo ZIP . Los distintos mtodos contenidos en esta clase se usan para fijar u obtener fragmentos de informacin acerca de la entrada actual. la clase ZipEntry se usa con las clases ZipFile y ZipInputStream para leer archivos ZIP. Algunos de los mtodos mas utilizados disponibles en la clase ZipEntry son los que se muestran junto con una descripcion en la tabla 2.
Tabla 2. Algunos mtodos utiles de la clase ZipEntry

Mtodo
public String getComment() public long getCompressedSize() public int getMethod() public String getName() public long getSize()

Descripcion Retorna un comentario sobre la entrada, null si no


tiene comentario

public long getTime() public void setComment(String c) public void setMethod(int method) public void setSize(long size) public void setTime(long time)

Retorna el tamao comprimido de la entrada, -1 si se desconoce Retorna el mtodo de compresin de la entrada, -1 si no esta especificado Retorna el nombre de la entrada Retorna el tamao sin comprimir de la entrada, -1 si se desconoce Retorna la fecha de modificacion de la entrada, -1 si no esta especificado Fija un comentario opcional para la entrada Fija el mtodo de compresion para la entrada Fija el tamao sin comprimir de la entrada Fija la fecha de modificacion de la entrada

Suma de Comprobacin (Checksum)


Algunas otras clases importantes del paquete java.util.zip son Adler32 y CRC32, estas clases implementan la interface java.util.zip.Checksum y calculan la suma de comprobacin requerida para la compresin de datos. El algoritmo Adler32 se conoce por ser mas rpido que el CRC32, y ste ultimo es conocido por ser ms confiable.

10

Compresin y descompresin de datos utilizando Java

las sumas de comprobacin se usan para detectar archivos o mensajes corruptos. Por ejemplo, imagina que quieres crear un archivo ZIP y despus transferirlo a una PC remota. Una vez que est en la mquina remota, usando la suma de comprobacion, puedes verificar si el archivo se corrompi durante la transmisin. Para mostrar como crear una suma de verificacion, hemos modificado el ejemplo 1 y el ejemplo 3, para usar CheckedInputStream y CheckedOutputStream, sto se muestra en los ejemplos 4 y 5. Ejemplo 4: Zip.java
import java.io.*; import java.util.zip.*; public class Zip { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream("c:\\temp\\myfigs.zip"); CheckedOutputStream checksum = new CheckedOutputStream(dest, new Adler32()); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum)); //out.setMethod(ZipOutputStream.DEFLATED); byte data[] = new byte[BUFFER]; // get a list of files from current directory File f = new File("."); String files[] = f.list(); for (int i=0; i<files.length; i++) { System.out.println("Adding: "+files[i]); FileInputStream fi = new FileInputStream(files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(files[i]); out.putNextEntry(entry); int count; while((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } out.close(); System.out.println("checksum: "+checksum.getChecksum().getValue()); } catch(Exception e) { e.printStackTrace(); } } }

Ejemplo 5: UnZip.java
import java.io.*; import java.util.zip.*; public class UnZip { 11

http://www.javahispano.com

public static void main (String argv[]) { try { final int BUFFER = 2048; BufferedOutputStream dest = null; FileInputStream fis = new FileInputStream("c:\\temp\\myfigs.zip"); CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32()); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum)); ZipEntry entry; while((entry = zis.getNextEntry()) != null) { System.out.println("Extracting: " +entry); int count; byte data[] = new byte[BUFFER]; // write the files to the disk FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = zis.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); } zis.close(); System.out.println("Checksum: "+checksum.getChecksum().getValue()); } catch(Exception e) { e.printStackTrace(); } } }

Para probar los ejemplos 4 y 5, compila las clases y ejecuta primero la clase Zip para crear un archivo ZIP (se calcular el valor de la suma de comprobacin y se mostrar en la pantalla ), despus ejecuta la clase UnZip para descomprimir el archivo (nuevamente el valor de la suma de comprobacin se mostrar en la pantalla). Los dos valores deben ser exactamente iguales, de no ser as, el archivo esta corrupto. Las sumas de verificacion son muy tiles para validar datos. Por ejemplo, puedes crear un archivo ZIP y enviarselo a un amigo junto con el valor de la suma de comprobacin. Tu amigo descomprime el archivo y compara el valor de la suma de comprobacin, si los dos valores son iguales, tu amigo sabe que el archivo es autntico.

Comprimiendo de Objetos
Hemos visto cmo comprimir datos que se encuentran en forma de archivos y agregarlos a un archivo apropiado. Pero qu sucede si los datos que deseamos comprimir no estn disponible en un archivo? Asumamos por ejemplo, que estas transfiriendo objetos grandes a travs de sockets. Para mejorar el desempeo de tu aplicacin, puedes querer comprimir los objetos antes de enviarlos por la red y descomprimirlos cuando lleguen a su destino. Como otro ejemplo, digamos quieres guardar objetos en el disco en un formato comprimido. El formato ZIP que esta basado en registros, no es muy conveniente para este trabajo. El formato GZIP es ms apropiado ya que funciona como un sencillo flujo de datos.

12

Compresin y descompresin de datos utilizando Java

Ahora, veamos un ejemplo de cmo comprimir objetos antes de escribirlos en el disco y cmo descomprimirlos despus de leerlos del disco. El ejemplo 6 es una sencilla clase que implementa la interface Serializable para indicarle a la JVM que deseamos serializar instancias de esta clase. Ejemplo 6: Employee.java
import java.io.*; public class Employee implements Serializable { String name; int age; int salary; public Employee(String name, int age, int salary) { this.name = name; this.age = age; this.salary = salary; } public void print() { System.out.println("Record for: "+name); System.out.println("Name: "+name); System.out.println("Age: "+age); System.out.println("Salary: "+salary); } }

Ahora, escribamos otra clase que cree un par de objetos de la clase Employee. El ejemplo 7 crea dos objetos (sarah y sam) de la clase Employee, despues guarda su estado en un archivo con un formato comprimido. Ejemplo 7 SaveEmployee.java
import java.io.*; import java.util.zip.*; public class SaveEmployee { public static void main(String argv[]) throws Exception { // creamos algunos objetos Employee sarah = new Employee("S. Jordan", 28, 56000); Employee sam = new Employee("S. McDonald", 29, 58000); // Serializamos los objetos sarah y sam FileOutputStream fos = new FileOutputStream("db"); GZIPOutputStream gz = new GZIPOutputStream(fos); ObjectOutputStream oos = new ObjectOutputStream(gz); oos.writeObject(sarah); oos.writeObject(sam); oos.flush(); oos.close(); fos.close(); } } Ahora, la clase ReadEmployee mostrada en el ejemplo 8, se usa para reconstruir el estado de los dos objetos. Una vez que el estado se ha reconstruido, el mtodo print se invoca en ellos. 13

http://www.javahispano.com

Ejemplo 8: ReadEmployee.java
import java.io.*; import java.util.zip.*; public class ReadEmployee { public static void main(String argv[]) throws Exception{ //des-serializamos los objetos sarah y sam FileInputStream fis = new FileInputStream("db"); GZIPInputStream gs = new GZIPInputStream(fis); ObjectInputStream ois = new ObjectInputStream(gs); Employee sarah = (Employee) ois.readObject(); Employee sam = (Employee) ois.readObject(); //mostramos los datos despues de reconstruir el estado de los objetos sarah.print(); sam.print(); ois.close(); fis.close(); } }

La misma idea se puede usar para comprimir grandes objetos que son enviados a travs de sockets. El siguiente fragmento de cdigo muestra como escribir objetos en un formato comprimido, desde el lado del servidor para el cliente:
// escribir para el cliente GZIPOutputStream gzipout = new GZIPOutputStream(socket.getOutputStream()); ObjectOutputStream oos = new ObjectOutputStream(gzipout); oos.writeObject(obj); gzipos.finish();

Y, el siguiente fragmento de cdigo muestra como descomprimir estos objetos del lado del cliente una vez recibidos desde el servidor:
// leer desde el servidor Socket socket = new Socket(remoteServerIP, PORT); GZIPInputStream gzipin = new GZIPInputStream(socket.getInputStream()); ObjectInputStream ois = new ObjectInputStream(gzipin); Object o = ois.readObject();

Y los archivos JAR?


El formato JAR(Java ARchive) esta basado en el formato normal ZIP con un archivo manifiesto opcional. Si deseas crear archivos JAR o extraer archivos desde una archivo JAR desde tus aplicaciones Java, usa el paquete java.util.jar, que proporciona clases para leer y escribir archivos JAR. El uso de las clases proporcionadas por el paquete java.util.jar es bastante similar al uso de las clases del paquete java.util.zip descritas en este artculo. Por consiguiente, podras adaptar mucho del cdigo de este artculo si deseas usar el paquete java.util.jar .

Conclusin
Este artculo plante las APIs que puedes usar para comprimir y descomprimir datos desde tus aplicaciones, con ejemplos a lo largo del artculo se mostr cmo usar el paquete
14

Compresin y descompresin de datos utilizando Java

para comprimir y descomprimir datos. Ahora tienes las herramientas necesarias para comprimir y descomprimir datos desde tus aplicaciones Java.
java.util.zip

El artculo tambin muestra cmo comprimir y descomprimir datos al vuelo para reducir el trfico de la red y mejorar el desempeo de tus aplicaciones cliente/servidor. La compresion de datos al vuelo , sin embargo, slo mejora el desempeo de aplicaciones cliente/servidor cuando los objetos que estn siendo comprimidos tiene un par de cientos de bytes como tamao. No podras observar sta mejora si los objetos que se estn comprimiendo y transfiriendo son sencillos objetos String, por ejemplo. Para ms informacin

El paquete java.util.zip El paquete java.util.jar Serializacin de Objetos Transportanto objetos sobre Sockets

Descarga el cdigo utilizado en este artculo.

Isaac Ruz, RuGI , egresado del ITI (Istmo de Tehuantepec, Oaxaca, Mexico) en la Carrera de Ingeniera en Sistemas Computacionales, es actualmente desarrollador independiente Java con intenciones de realizar el examen de certificacin Cuando no esta programando o navegando (?) le gusta mucho leer todo aquello que le de el mas pequeo indicio de como llegar al Valhala o por lo menos a Avalon =:D Para cualquier duda o comentario: RuGI@javahispano.com

15

You might also like