View
518
Download
0
Category
Preview:
Citation preview
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 1/15
Compresión y descompresión de datos utilizando Java
1
Compresión y descompresión de datosutilizando Java
Autor: Qusay H. Mahmoud/Konstantin KladkoTraducción/Adaptación: RuGI
URLOriginal:http://developer.java.sun.com/developer/technicalArticles/Programming/compression/
Muchas fuentes de información contienen datos redundantes o datos que no son muyrevelantes para la información que se quiere guardar. Esto produce grandes cantidades dedatos que se transfieren entre el cliente y el servidor de aplicaciones o entre computadoras en
general. La solución obvia a estos problemas de almacenamiento de los datos y traslado de lainformación es instalar dispositivos del almacenamiento adicionales y extender los medios de
comunicación existentes. Hacer esto, sin embargo, requiere un incremento en los costos deoperación en una organización. Un método para reducir una porción el almacenamiento de losdatos y la tranferencia de la información es a través de representaciones de los datos con un
codigo mas eficiente. Este artículo presenta una ligera introducción a la compresion ydescompresion de datos, y muestra cómo 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 unasolución eficaz. Este artículo:
• Muestra brevemente las generalidades de la compresión de datos
• Describe el paquete java.util.zip
• Muestra cómo usar este paquete para comprimir y descomprimir datos• Muestras cómo comprimir y descomprimir objetos serializados para ahorrar espacio
en disco• Muestras cómo comprimir y descomprimir datos al vuelo (antes de transmitir) para
mejorar el desempeño de aplicaciones cliente/servidor
Generalidades de la compresión de datos
Un ejemplo sencillo de redundancia de datos en un archivo es la repetición de caracteres. Porejemplo, considera la siguiente cadena:
BBBBHHDDXXXXKKKKWWZZZZ
Este cadena puede ser codificada y compactada reemplazando cada subcadena repetida decarácteres por un solo carácter repetido y un número que representa el número de veces que el
carácter se repite. La cadena anterior puede codificarse así:
4B2H2D4X4K2W4Z
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 2/15
http://www.javahispano.com
2
Aqui, "4B" significa cuatro B's, "2H" significa dos H's, y asi sucesivamente. La compresiónde cadenas con este algoritmo se conoce somo RLE (run-length encoding)
Como otro ejemplo, considera el almacenamiento de una imagen rectangular. Como unasencilla imagen de un mapa de bits, ésta se puede almacenar como muestra la Figura 1.
0000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000111111111111111111110000000000
000000000010000000000000000001000000000000000000001000000000000000000100000000000000000000100000000000000000010000000000
00000000001111111111111111111100000000000000000000000000000000000000000000000000
Fig.1. Un mapa de bits con información para el RLE
Otro manera podría ser guardar la imagen como un metafile gráfico:
Rectangle 11, 3, 20, 5
Que significa; el rectángulo comienza en la coordenada (11,3) y tiene 20 pixeles de ancho y 5
de alto.
La imagen rectangular puede comprimirse utilizando RLE a través del conteo de bitsidenticos, así:
0, 400, 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 línea nos dice que la primera línea del mapa de bit's consiste en 40 0's. La terceralínea dice que la tercera línea del mapa de bit's consiste en 10 0's seguidos por 20 1's yseguidos por 10 0's más, y así sucesivamente para las otras líneas.
Nota que RLE requiere representaciones diferentes para el archivo y su versión codificada,
dependiendo del tipo del archivo. Por consiguiente, este método no puede trabajar con todoslos tipos de archivos. Otras técnicas de compresion incluyen variaciones de RLE, una es VLE
variable-length encoding (también conocida como código Huffman ), y muchas otros. Paramás información, hay muchos libros disponible sobre técnicas de compresion de datos éimagenes.
Hay muchos beneficios con la compresión de los datos. No obtante, la ventaja principal es
reducir requisitos de almacenamiento. También, para comunicaciones de los datos, latransferencia de datos comprimidos aumenta la cantidad de información transmitida. Observa
que la compresión de datos puede implementarse con el hardware ya existente, con software ousando dispositivos de hardware especiales que ya incorporán las técnicas de compresión. LaFigura 2 muestra un diagrama de bloques basico sobre la compresión de datos.
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 3/15
Compresión y descompresión de datos utilizando Java
3
_________________
----------------------> Compresion ---------------------->
Datos Originales de Datos comprimidos
<--------------------- datos <---------------------
_________________
Fig.2. Diagrama de Bloques. Compresión de datos
ZIP vs GZIP
Si estás trabajando con Windows, podrías estar familiarizado con la herramienta WinZip quese utiliza para crear un archivo comprimido y para extraer archivos de un archivocomprimido. 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 archivoscon los formatos ZIP y GZIP. También te proporciona clases para comprobar las sumas decontrol 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 laTabla 1.
Tabla 1. El paquete java.util.zip
Elemento Tipo Descripción
Checksum InterfaceRepresenta un dato de la suma de control (data
checksum). Implementado por las clases Adler32 yCRC32
Adler32 ClaseUsado para calcular la suma de control(checksum) de
un flujo de datos
CheckedInputStream ClaseUn flujo de entrada que guarda la suma de control delos datos que estan siendo leídos.
CheckedOutputStream ClaseUn flujo de salida que guarda la suma de control delos datos que estan siendo escritos.
CRC32 ClaseUsado para calcular la suma de control CRC32 de un
flujo de datos
Deflater Clase Soporte para compresion usando la librería ZLIB
DeflaterOutputStream ClaseUn flujo de salida filtrado para la compresión dedatos con el formato de compresión deflate
GZIPInputStream ClaseUn flujo de entrada filtrado para leer datos
comprimidos con el formtatoGZIP
GZIPOutputStream ClaseUn flujo de salida filtrado para escribir datos
comprimidos con el formato GZIP
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 4/15
http://www.javahispano.com
4
Inflater Clase Soporte para descompresion usando la librería ZLIB
InflaterInputStream ClaseUn flujo de entrada filtrado para la descompresion de
datos con el formato de compresión deflate
ZipEntry Clase Representa la entrada de un archivo ZIP
ZipFile Clase Usado para leer entradas de un archivo ZIP
ZipInputStream ClaseUn filtro de entrada para leer archivos con el formatoZIP
ZipOutputStream ClaseUn filtro de salida para escribir archivos con el
formato ZIP
DataFormatException Clase deexcepcion
Lanza una excepción para señalar un error en elformato de los datos
ZipException Clase de
exepcion
Lanza una excepción para señalar un error en el
formato Zip
Nota: La librería de compresión ZLIB se desarrolló inicialmente como parte
de la norma PNG(Portable Network Graphics) que no esta protegida porpatentes.
Comprimiendo y descomprimiendo datos desde un archivo ZIP
El paquete java.util.zip proporciona clases para la compresión y descompresión de datos.
La descompresión 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 siguientefragmento de código 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 elmétodo 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 lasiguiente manera:
int BUFFER = 2048;
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 5/15
Compresión y descompresión de datos utilizando Java
5
FileOutputStream fos = new
FileOutputStream(entry.getName());
BufferedOutputStream dest = new
BufferedOutputStream(fos, BUFFER);
Nota: En el código 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 tamaño del buffer a utilizar es mucho mas grande que512 bytes (en este ejemplo 2048). Mientras que ZipOutputSream no te permite
modificar el tamaño del buffer , GZIPOutputStream si lo hace; puedes
especificar el tamaño del buffer interno como un argumento de su constructor.
En este segmento de código, un flujo de salida de archivo se crea usando el nombre de la(s)entrada(s) ZIP que puede recuperarse usando el método 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 pasándole como parámetro 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/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 6/15
http://www.javahispano.com
6
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 leídas secuencialmente
Nota: Otra diferencia fundamental entre ZipInputSream y ZipFile és enterminos 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 combinación de ZipInputStream y FileInputStream. Por otro lado, si elarchivo es abierto usando ZipFile(fileName) entonces es colocado en la
memoria intermedia, así si ZipFile(fileName) es llamado otra vez el archivo
sólo 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 desempeño de ZipFile es superior a
ZipInputStream. Por otro lado, si los contenidos del mismo ZIP, son
frecuentemente modificados y recargados durante la ejecución del programaentonces 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");
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 7/15
Compresión y descompresión de datos utilizando Java
7
2. Usa el método entries, que retorna un objeto Enumeration, después con un cicloobten 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 método 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. byte data[] = new byte[BUFFER];
12. FileOutputStream fos = new
13. FileOutputStream(entry.getName());
14. dest = new BufferedOutputStream(fos, BUFFER);
15. while ((count = is.read(data, 0, BUFFER)) != -1){
16. dest.write(data, 0, count);
17. }
18. Finalmente, cierra todos los fujos de entrada y salida:19. dest.flush();
20. dest.close();
21. is.close();
El código completo de este programa se muestra en el ejemplo 2. Nuevamente, para probaresta 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());
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 8/15
http://www.javahispano.com
8
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 creación de un archivo
ZIP involucra la siguiente serie de pasos:
1. El primer paso es crear un objeto ZipOutputStream ; le pasaremos como parámetro el
flujo de salida del archivo al cual queremos escribir. Aqui se muestra la manera decrear un archivo ZIP llamado "myfigs.zip":
2. FileOutputStream dest = new
3. FileOutputStream("myfigs.zip");
4. ZipOutputStream out = new
5. ZipOutputStream(new
BufferedOutputStream(dest));
6. Una vez que el flujo de salida objetivo es creado, el siguiente paso es abrir el o losarchivos origen de los datos. En este ejemplo, los archivos a partir de los cuales secreará el archivo ZIP son aquellos archivos que se escuentren en el directorio actual.
El método list se usa en este ejemplo para obtener la lista de los archivos que se
encuentran en el directorio actual:7. File f = new File(".");
8. String files[] = f.list();
9. for (int i=0; i<files.length; i++) {
10. System.out.println("Adding: "+files[i]);
11. FileInputStream fi = new FileInputStream(files[i]);
12. // creamos una entrada zip
13. // agregamos entradas zip al archivo
14. }
Nota:El código anterior es capaz de comprimir todos los archivos que se encuentranen el directorio actual. No maneja subdirectorios. Como ejercicio, puedes intentar
modificar el ejemplo 3 para que maneje subdirectorios
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 9/15
Compresión y descompresión de datos utilizando Java
9
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 método putNextEntry:18. out.putNextEntry(entry);
19. Escribimos los datos en el archivo ZIP:20. int count;
21. while((count = origin.read(data, 0, BUFFER)) != -1) {
22. out.write(data, 0, count);
23. }
24. Finalmente, cerramos los flujos de entrada y salida:25. origin.close();
26. out.close();
El código 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( newBufferedOutputStream(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();
}
}}
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 10/15
http://www.javahispano.com
10
Nota:Las entradas pueden ser agregadas al archivo ZIP de forma comprimida(DEFLATED) o no comprimida(STORED). El método setMethod se usa para
fijar el método de almacenamiento. Por ejemplo, para fijar el método 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 métodos contenidos en esta clase se usan para fijar u obtener fragmentos de
información acerca de la entrada actual. la clase ZipEntry se usa con las clases ZipFile yZipInputStream para leer archivos ZIP. Algunos de los métodos mas utilizados disponibles
en la clase ZipEntry son los que se muestran junto con una descripcion en la tabla 2.
Tabla 2. Algunos métodos utiles de la clase ZipEntry
Método Descripcion
public String getComment() Retorna un comentario sobre la entrada, null si notiene comentario
public long
getCompressedSize() Retorna el tamaño comprimido de la entrada, -1 si se
desconoce
public int getMethod() Retorna el método de compresión de la entrada, -1 si no
esta especificadopublic String getName() Retorna el nombre de la entrada
public long getSize() Retorna el tamaño sin comprimir de la entrada, -1 si se
desconoce
public long getTime() Retorna la fecha de modificacion de la entrada, -1 si no
esta especificado
public void setComment(String
c) Fija un comentario opcional para la entrada
public void setMethod(int
method) Fija el método de compresion para la entrada
public void setSize(longsize) Fija el tamaño sin comprimir de la entrada
public void setTime(long
time) Fija la fecha de modificacion de la entrada
Suma de Comprobación (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
comprobación requerida para la compresión de datos. El algoritmo Adler32 se conoce por ser
mas rápido que el CRC32, y éste ultimo es conocido por ser más confiable.
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 11/15
Compresión y descompresión de datos utilizando Java
11
las sumas de comprobación se usan para detectar archivos o mensajes corruptos. Por ejemplo,imagina que quieres crear un archivo ZIP y después transferirlo a una PC remota. Una vez
que está en la máquina remota, usando la suma de comprobacion, puedes verificar si elarchivo se corrompió durante la transmisión. 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 {
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 12/15
http://www.javahispano.com
12
public static void main (String argv[]) {
try {
final int BUFFER = 2048;
BufferedOutputStream dest = null;
FileInputStream fis = new
FileInputStream("c:\\temp\\myfigs.zip");
CheckedInputStream checksum = newCheckedInputStream(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 comprobación y se mostrará en la pantalla ),
después ejecuta la clase UnZip para descomprimir el archivo (nuevamente el valor de la suma
de comprobación 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 comprobación. Tu amigo descomprime el archivo y compara el valor de la suma
de comprobación, si los dos valores son iguales, tu amigo sabe que el archivo es auténtico.
Comprimiendo de Objetos
Hemos visto cómo 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 están disponibleen un archivo? Asumamos por ejemplo, que estas transfiriendo objetos grandes a través de
sockets. Para mejorar el desempeño de tu aplicación, puedes querer comprimir los objetosantes de enviarlos por la red y descomprimirlos cuando lleguen a su destino. Como otroejemplo, 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 esmás apropiado ya que funciona como un sencillo flujo de datos.
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 13/15
Compresión y descompresión de datos utilizando Java
13
Ahora, veamos un ejemplo de cómo comprimir objetos antes de escribirlos en el disco y cómodescomprimirlos después de leerlos del disco. El ejemplo 6 es una sencilla clase queimplementa 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 método print se invoca en ellos.
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 14/15
http://www.javahispano.com
14
Ejemplo 8: ReadEmployee.java
import java.io.*;
import java.util.zip.*;
public class ReadEmployee {
public static void main(String argv[]) throwsException{
//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 través desockets. El siguiente fragmento de código muestra como escribir objetos en un formatocomprimido, 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 código muestra como descomprimir estos objetos del lado delcliente 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 artículo.
Por consiguiente, podras adaptar mucho del código de este artículo si deseas usar el paquete
java.util.jar .
Conclusión
Este artículo planteó las APIs que puedes usar para comprimir y descomprimir datos desde tus
aplicaciones, con ejemplos a lo largo del artículo se mostró cómo usar el paquete
5/9/2018 comprimir - slidepdf.com
http://slidepdf.com/reader/full/comprimir 15/15
Compresión y descompresión de datos utilizando Java
15
java.util.zip para comprimir y descomprimir datos. Ahora tienes las herramientasnecesarias para comprimir y descomprimir datos desde tus aplicaciones Java.
El artículo también muestra cómo comprimir y descomprimir datos al vuelo para reducir eltráfico de la red y mejorar el desempeño de tus aplicaciones cliente/servidor. La compresion
de datos al vuelo , sin embargo, sólo mejora el desempeño de aplicaciones cliente/servidorcuando los objetos que están siendo comprimidos tiene un par de cientos de bytes comotamaño. No podras observar ésta mejoría si los objetos que se están comprimiendo y
transfiriendo son sencillos objetos String, por ejemplo.
Para más información
• El paquete java.util.zip
• El paquete java.util.jar • Serialización de Objetos • Transportanto objetos sobre Sockets
Descarga el código utilizado en este artículo.
Isaac Ruíz, RuGI , egresado del ITI (Istmo de Tehuantepec, Oaxaca, Mexico) en la Carrerade Ingeniería en Sistemas Computacionales, es actualmente desarrollador independiente Javacon intenciones de realizar el examen de certificación
Cuando no esta programando o navegando (¿?) le gusta mucho leer todo aquello que le de elmas pequeño indicio de como llegar al Valhala o por lo menos a Avalon =:D
Para cualquier duda o comentario: RuGI@javahispano.com
Recommended