Posted by: carloslone | August 27, 2007

Comprimiendo Archivos en .Net 2.0

Una de las novedades del .Net Framework 2.0 es la inclusión de librerías que soportan la compresión de información, ésta a pesar de ser una muy útil funcionalidad es desconocida por muchas personas. En este post quiero aprovechar a explicarles como pueden ustedes implementar fácilmente la compresión y des-compresión de archivos haciendo uso de dos de los formatos mas utilizados para la compresión de datos: Gzip y Deflate. En el .net Framework 2.0 se implementaron dos nuevas clases incluidas en el NameSpace System.IO.Compression se trata de: GZipStream y DeflateStream. A continuación detallo los pasos necesarios para poder implementar el proceso en una aplicación:

1. Crear una nueva aplicación de consola llamada ComprimiendoArchivos. (Menu File –> New Project )

2. Vamos agregar una clase llamada CompresionArchivos y declararemos dos métodos “ComprimirArchivo” y “DescomprimirArchivo” los cuales recibirán dos parametros “archivoEntrada” y “archivoSalida” de tipo string.

3. Ahora implementaremos el método “ComprimirArchivos”, en donde utilizaremos dos objetos de tipo FileStream que nos serviran para leer el archivo origen y guardar el archivo comprimido. La magia sucede al hacer uso de la clase GZipStream, la cual en su constructor recibe como argumentos el Stream de salida y un modo de Compresion para indicar si vamos a comprimir o des-comprimir datos. También hacemos uso del metodo “Write” para escribir la información al stream de salida. Veamos el siguiente código para comprender mejor mi explicación:

VB (click en la imagen para ampliarla)

Click para ampliar la imagen

C# (click en la imagen para ampliarla)

Click para ampliar la imagen

En el método ComprimirArchivo vemos lo sencillo que es implementar el proceso de compresión de un archivo, también es importante identificar el uso de la clausula Using la cual es muy util al trabajar con streams por que ésta se asegura de cerrar todos los streams al momento de terminar de ser utilizados. El metodo File.OpenRead(archivoEntrada) es utilizado para abrir el archivo origen en modo de lectura y asignarlo a un FileStream. El método File.Create(archivoSalida) nos permite crear un nuevo archivo en nuestro disco duro. Por ultimo veamos el uso de la clase GZipStream, el constructor recibe dos parametros, el primero es para identificar el stream de salida al que asociaremos la clase (para el ejemplo destFile), el segundo indica el modo de comportamiento que utilizaremos  (para el ejemplo Compress). Luego utilizamos un arreglo de Bytes para leer la información del archivo origen y finalmente escribimos los datos comprimidos por medio de la función compStream.Write a la cual le pasamos como parametro el arreglo de bytes.

4. Ahora implementaremos el método “DescomprimirArchivo”, como ustedes veran a continuación la forma de implementación es la misma, con la unica diferencia en la forma en que inicializamos el objeto tipo GZipStream, también aqui no podemos hacer uso de la instrucción compStream.Lenght por que nos genera una excepción indicando que esta funcionalidad no esta implementada. Para leer los datos utilizaremos un ciclo while para ir leyendo la información. Veamos como queda este método:

VB (click en la imagen para ampliarla)

Click para ampliar la imagen

C# (click en la imagen para ampliarla)

Click para ampliar la imagen

Como vemos los únicos cambios realizados fueron los siguientes: El constructro de la clase GZipStream ahora utiliza el modo “Decompress” para indicar que vamos a descomprimir la información de un archivo. Luego leemos toda la información del archivo haciendo uso de la instrucción compStream.ReadByte().

5. Para hacer uso de la clase solo invocamos los dos metodos desde Sub Main().

VB (click en la imagen para ampliarla)

Click para ampliar la imagen

C# (click en la imagen para ampliarla)

Click para ampliar la imagen

Como ustedes pueden apreciar, la implementación de metodos para comprimir y des-comprimir información es muy sencila en .net. Si quieren hacer uso del algoritmo DEFLATE, lo unico que deben modificar en la clase que hemos desarrollado es el uso de la Clase GzipStream por DeflateStream, incluso el constructor de la clase DeflateStream utiliza los mismos argumentos que la clase GzipStream. Una pregunta válida sería ¿Cuando utilizar GZipStream y cuando utilizar DeflateStream ?, ambas clases utilizan el mismo algoritmo de compresión, la única diferencia es que el formato GZip agrega información en el header para que pueda ser interpretada por programas como winzip. Mientras que Deflate no agrega esta información, por lo que si no van a utilizar los archivos con aplicaciones comerciales, es más recomendable utilizar deflate y les quedara un poco más pequeño el archivo.

Les dejo un link para que puedan bajar el proyecto con el codigo: Bajar Codigo Ejemplo

Espero que este simple ejemplo les sea de mucha utilidad. Hasta la proxima !!!

Saludos,

Carlos A. Lone

Etiquetas de del.icio.us: , , , ,

 

 

Etiquetas de Technorati: , , , ,


Responses

  1. Hola
    No se si a ti te ocurra pero el archivo que me da como resultado (.zip) es mas grande que el archivo no comprimido, si mi archivo original pesa 312Kb el comprimido llega a 400Kb, si sabes de algo me comentas por favor. El archivo que estoy zipeando es un jpg.
    Gracias
    Arturo

  2. Estimado Arturo,

    Respecto a tu pregunta mi respuesta es la siguiente. En primer lugar el formato jpb ya es un formato comprimido, por lo que generalmente al zippear un jpg realmente es poco lo que se gana. Respecto a tu pregunta de por que quedo mas grande el archivo te va la respuesta. No se en que formato de encripcion utilizaste, sin embargo si fue por ejemplo gzip entonces este agrega una informacion en el header del archivo, entonces si jpg ya es un formato comprimido el algoritmo de compresion no hara mucho, entonces el tamaño del archivo deberia ser muy parecido al original pero si le agregamos los headers entonces alli es donde crece el archivo. Tambien, gzip no necesariamente es el mejor algoritmo de encripcion, existen otros mejores, por lo que si en realidad andas en busca de optimización de espacio te recomiendo evaluar esta otra herramienta: SharpZipLib aqui te dejo un articulo http://www.elguille.info/NET/dotnet/SharpZipLib.htm

    Saludos

    Carlos A. Lone

  3. Hola, se puede realizar la compresion en multiples volumenes? algo asi como para transportarlos en diskettes. Siempre utilizando System.IO.Compression. Gracias

  4. Estimado Leo, respecto a tu pregunta si es posible, la verdad no se como estes haciendo esto, si en una aplicacion visual (Winforms) o en una aplicacion de consola, pero independientemente de eso puedes hacer uso de la clase DriveInfo y a través del método GetDrives para validar los posibles drives validos en tu maquina y con esto poder grabar en cualquiera de estos, pudiendo ser diskettes, usb,e tc.

  5. Hola, al probar el ejemplo que pones para comprimir archivos en gzip me encuentro con que el zip que se crea me manda el siguiente error:

    Cannot open file: it does not appear to be a valid archive. If you downloaded this file,try downloading the file again.

    Esto es cuando intento abrir el zip generado con winzip, por que ocurre esto??

  6. Estimado Victor,

    Para poder ver tu archivo con winzip por favor nombralo con la extensión .gz, alli si te va funcionar.

    Saludos,

    Carlos A. Lone

  7. Hola, estoy interesado en comprimir varios archivos con estos metodos…¿como se hace? gracias!

  8. Hola Carlos, muy interesante tu post, la verdad me ha servido mucho, incluso este tipo de compresion es mas facil que el SharpZipLib, de todas maneras me gustaria saber si e sposible hacer la compresion de mas de un archivo; es decir, como hago para comprimir 2 o mas imagenes gif que se encuentren en la misma carpeta???

  9. jose, si quieres hacer algo con carpetas te doy dos opciones, o que tu administres por programacion adjuntar varios archivos, o lo mejor utilizar la sharpziplib, como en este ejemplo http://www.elguille.info/NET/dotnet/SharpZipLib.htm cualquier cosa estoy a la orden

    Saludos,

    Carlos A. Lone

  10. […] Como ustedes sabrán hace algún tiempo escribí un artículo titulado "Comprimiendo Archivos en .net 2.0" el cual ha tenido bastante aceptación entre mis lectores. Una de las solicitudes que […]

  11. […] Como ustedes sabrán hace algún tiempo escribí un artículo titulado "Comprimiendo Archivos en .net 2.0" el cual ha tenido bastante aceptación entre mis lectores. Una de las solicitudes que […]

  12. Hola Carlos, esto del System.IO.Compression es una maravilla, bueno yo tengo poco tiempo de haber incursionado en .Net y no lo conocia.
    Tengo una consulta existirá la forma con este namespace de crearle algun tipo de contraseña o algún tipo de seguridad para el archivo que comprimido que se genera??

    Muchas Gracias…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: