16 mayo, 2007

Leyendo y escribiendo archivos comprimidos

En días anteriores escribí acerca de cómo leer y escribir archivos, hoy quiero ampliar este tema explicando cómo manejar archivos comprimidos.

Para crear y abrir archivos comprimidos el namespace system.io nos facilita dos clases Gzipstream y el Deflatestream. Estas clases implementan el mismo algoritmo de compresión, la principal diferencia radica en que el Gzip almacena información adicional en el encabezado, esto provoca que los archivos comprimidos con Gzip sean un poco más grandes que los comprimidos con Deflate, pero, esto le permite ser más compatible. Ambos algoritmos limitados a archivos inferiores a 4gb.

Si vamos a comprimir un archivo que vamos a enviar a otras máquinas es recomendable utilizar el Gzip y no el Deflate. Pero veamos un ejemplo de cómo usar la clase GzipStream

Imports system.io

Imports System.IO.Compression

Module Module1

Sub Main()

Dim NombreArchivoOrigen As String = "c:\temp\log.txt"

Dim NombreArchivoComprimido As String = "c:\temp\log.txt.gz"

Dim ArchivoOrigen As FileStream = File.Open(NombreArchivoOrigen, FileMode.Open, FileAccess.Read)

Dim ArchivoDestino As FileStream = File.Open(NombreArchivoComprimido, FileMode.CreateNew, FileAccess.Write)

Dim MiStream As New GZipStream(ArchivoDestino, CompressionMode.Compress)

'Se utiliza integer en lugar de byte para poder almacenar -1.

Dim Mibyte As Integer = ArchivoOrigen.ReadByte()

While Mibyte <> -1

MiStream.WriteByte(CType(Mibyte, Byte))

Mibyte = ArchivoOrigen.ReadByte()

End While

MiStream.Close()

ArchivoOrigen.Close()

ArchivoDestino.Close()

Dim infoarchivoorigen As FileInfo = New FileInfo(NombreArchivoOrigen)

Dim infoarchivocomprimido As FileInfo = New FileInfo(NombreArchivoComprimido)

Console.WriteLine("Tamaño original : {0}", infoarchivoorigen.Length)

Console.WriteLine("Tamaño comprimido: {0}", infoarchivocomprimido.Length)

Console.ReadKey()

End Sub

End Module

Ahora, que si no queremos usar el Gzip sino el deflate solo requerimos de cambiar la clase GzipStream por DeflateStream el resto del procedimiento es igual, veamos:

Imports system.io

Imports System.IO.Compression

Module Module1

Sub Main()

Dim NombreArchivoOrigen As String = "c:\temp\log.txt"

Dim NombreArchivoComprimido As String = "c:\temp\log.txt.gz"

Dim ArchivoOrigen As FileStream = File.Open(NombreArchivoOrigen, FileMode.Open, FileAccess.Read)

Dim ArchivoDestino As FileStream = File.Open(NombreArchivoComprimido, FileMode.CreateNew, FileAccess.Write)

Dim MiStream As New DeflateStream(ArchivoDestino, CompressionMode.Compress)

'Se utiliza integer en lugar de byte para poder almacenar -1.

Dim Mibyte As Integer = ArchivoOrigen.ReadByte()

While Mibyte <> -1

MiStream.WriteByte(CType(Mibyte, Byte))

Mibyte = ArchivoOrigen.ReadByte()

End While

MiStream.Close()

ArchivoOrigen.Close()

ArchivoDestino.Close()

Dim infoarchivoorigen As FileInfo = New FileInfo(NombreArchivoOrigen)

Dim infoarchivocomprimido As FileInfo = New FileInfo(NombreArchivoComprimido)

Console.WriteLine("Tamaño original : {0}", infoarchivoorigen.Length)

Console.WriteLine("Tamaño comprimido: {0}", infoarchivocomprimido.Length)

Console.ReadKey()

End Sub

End Module

Ahora que ya sabemos cómo comprimir, debemos aprender a descomprimir, la lógica es la misma, solo debemos invertirla. Veamos:

Imports system.IO

Imports System.IO.Compression

Module Module1

Sub Main()

Dim NombreArchivoComprimido As String = "c:\temp\log.txt.gz"

Dim NombreArchivoDestino As String = "c:\temp\log.txt"

Dim ArchivoOrigen As FileStream = File.Open(NombreArchivoComprimido, FileMode.Open, FileAccess.Read)

Dim ArchivoDestino As FileStream = File.Open(NombreArchivoDestino, FileMode.CreateNew, FileAccess.Write)

Dim MiStream As New GZipStream(ArchivoOrigen, CompressionMode.Decompress)

Dim Mibyte As Integer = MiStream.ReadByte()

While Mibyte <> -1

ArchivoDestino.WriteByte(CType(Mibyte, Byte))

Mibyte = MiStream.ReadByte()

End While

MiStream.Close()

ArchivoOrigen.Close()

ArchivoDestino.Close()

Dim infoarchivoorigen As FileInfo = New FileInfo(NombreArchivoComprimido)

Dim infoarchivodestino As FileInfo = New FileInfo(NombreArchivoDestino)

Console.WriteLine("Tamaño comprimido : {0}", infoarchivoorigen.Length)

Console.WriteLine("Tamaño destino : {0}", infoarchivodestino.Length)

Console.ReadKey()

End Sub

End Module

El anterior ejemplo descomprime utilizando GZip si el archivo que deseamos descomprimir fue comprimido mediante Deflate solo tenemos que cambiar la clase y listo, el resto es exactamente igual.

No hay comentarios.: