Descargar Fuente
El intercambiar datos dentro de nuestra organización sería mucho mas eficiente si estos datos no ocuparan mucho espacio ya que de ese modo al ser transferidos sobre nuestra red no la sobrecargarían y el transporte sería muchísimo mas rapido. Existen muchos algoritmos para compresión de datos tanto de caracter privado como publico y que pueden ser utilizados para este propósito.
Microsoft, conociendo la importancia de tener estos algoritmos y de su uso, ha implementado dentro del Framework 2.0 un conjunto de clases que nos permita utlizarlos de manera muy sencilla y rápida, estas clases las podemos encontrar dentro del Namespace «System.IO.Compression», y se llaman DeflateStream y GZipStream.
La clase DeflateStream usa el algoritno de compresión «DEFLATE» que lo podemos encontrar detallado en el RFC 1951 (URL: http://www.faqs.org/rfcs/rfc1951.html) y que es libre sin patentes ni nada por el estilo e implementado en muchas herramientas de compresión, en si se basa en la combinación del Algoritmo LZ77 y la codificación Huffman.
Ahora la clase GZipStream se basa también en el algoritmo de compresión DEFLATE agregándole cierta metadata tanto en la cabecera y un pie de página. Por lo mismo dentro del framework 2.0 se podría decir que GZipStream es una simple extensión de la clase Deflate con el agregado de una cabecera y un pie de página haciendolo compatible con otros comprimidores/descomprimidores tal como es WinZip o Winrar ( Ojo en el caso de estos productos, además de permitir comprimir/Descomprimir manejan tambien el concepto de archivameinto por lo tanto los resultados que obtengamos comparados a estos productos no van a ser los mismos).
Tambien podríamos decir que en .NET se tiene la restricción a un máximo de 4 Gigas de tamaño para usar estas clases, aunque no es un gran inconveniente, se podría decir que es totalmente manejable 🙂
Ahora la implementación del mismo es muy sencilla, como primer paso requerimos hacer lo siguiente:
1 using System.IO.Compression;
De esta forma importamos el namespace que nos va a permitir trabajar con las clases ya definidas anteriormente:
Luego de ello vamos a definir un método que nos permita realizar la compresión usando la Clase GZipStream:
1 public static void GZipCompresion(string strNombreArchivo)
2 {
3 FileStream fsArchivo;
4 try
5 {
6 // Leemos el archivo a comprimir
7 fsArchivo = new FileStream(strNombreArchivo, FileMode.Open, FileAccess.Read, FileShare.Read);
8 //Definimos el buffer con el tamaño del archivo
9 byte[] btBuffer = new byte[fsArchivo.Length];
10 //Almacenamos los bytes del archivo en el buffer
11 int intCount = fsArchivo.Read(btBuffer, 0, btBuffer.Length);
12 fsArchivo.Close();
13
14 //Definimos el nuevo stream que nos va a permitir grabar el zip
15 FileStream fsSalida = new FileStream(strNombreArchivo + «.zip», FileMode.Create, FileAccess.Write);
16 //Rutina de compresion usando GZipStream
17 GZipStream gzsArchivo = new GZipStream(fsSalida, CompressionMode.Compress, true);
18 //Escribimos el resultado
19 gzsArchivo.Write(btBuffer, 0, btBuffer.Length);
20 gzsArchivo.Close();
21
22 //Cerramos el archivo
23 fsSalida.Flush();
24 fsSalida.Close();
25
26 MessageBox.Show(«Compresion realizada correctamente al archivo: « + strNombreArchivo + «.zip»);
27 }
28 catch (Exception ex)
29 {
30 MessageBox.Show(«Ocurrió un error al comprimir: « + ex.Message);
31
32 }
33 }
Y con eso ya tendríamos implementado el método para comprimir, para llamarlo desde un formulario windows podríamos realizar lo siguiente:
1 private void btnComprimir_Click(object sender, EventArgs e)
2 {
3 OpenFileDialog ofd = new OpenFileDialog();
4 if (ofd.ShowDialog() == DialogResult.OK)
5 {
6 GZipCompresion(ofd.FileName);
7 }
8 }
Ahora para realizar la descompresión se torna un poquito más complicado debido a que se requiere el tamaño del buffer en donde almacenar el resultado de la descompresión, aca tenemos la implementación del mismo:
1 public static void GZipDescompresion(string strNombreArchivo)
2 {
3 FileStream fsArchivo;
4 try
5 {
6 //Leemos archivo a descomprimir
7 fsArchivo = new FileStream(strNombreArchivo, FileMode.Open, FileAccess.Read, FileShare.Read);
8 GZipStream gzsArchivo = new GZipStream(fsArchivo, CompressionMode.Decompress);
9
10 //Codigo implementado para conocer las dimensiones que va a tener nuestro buffer, acumulativo.
11 int offset = 0;
12 int intCountBytes = 0;
13 byte[] btSmallBuffer = new byte[100];
14 while (true)
15 {
16 int bytesRead = gzsArchivo.Read(btSmallBuffer, 0, 100);
17 if (bytesRead == 0)
18 {
19 break;
20 }
21 offset += bytesRead;
22 intCountBytes += bytesRead;
23 }
24 //Creamos el buffer con el tamaño requerido
25 byte[] buffer = new byte[intCountBytes];
26
27 //Leemos el contenido del archivo comprimido al buffer
28 fsArchivo = new FileStream(strNombreArchivo, FileMode.Open, FileAccess.Read, FileShare.Read);
29 gzsArchivo = new GZipStream(fsArchivo, CompressionMode.Decompress);
30 int intCount = gzsArchivo.Read(buffer, 0, intCountBytes);
31 gzsArchivo.Close();
32
33 //Escribimos la salida a un nuevo archivo, ya descomprimido
34 FileStream fsSalida = new FileStream(strNombreArchivo.Substring(0, strNombreArchivo.Length – 4), FileMode.Create, FileAccess.Write);
35 fsSalida.Write(buffer, 0, intCountBytes);
36 fsSalida.Flush();
37 fsSalida.Close();
38
39 MessageBox.Show(«Descompresion realizada correctamente al archivo: « + strNombreArchivo.Substring(0, strNombreArchivo.Length – 4) + «.zip»);
40
41 }
42 catch (Exception ex)
43 {
44 MessageBox.Show(«Ocurrió un error al descomprimir: « + ex.Message);
45
46 }
47 }
Para llamar a este método desde un formulario windows:
1 private void btnDescomprimir_Click(object sender, EventArgs e)
2 {
3 OpenFileDialog ofd = new OpenFileDialog();
4 if (ofd.ShowDialog() == DialogResult.OK)
5 {
6 GZipDescompresion(ofd.FileName);
7 }
8 }
Bastante sencilla la implementación, y es que justamente para ello esta el Framework, para hacernos la vida mas sencilla 🙂
Espero sea de utilidad, luego publicaré el código fuente para su descarga,
Feliz Navidad 🙂
Ivan Mostacero