sexta-feira, agosto 21, 2009

Compactação - Parte 7

Fechando esta série de posts, vamos ver como usar a zlib no .Net. A empresa Component Ace adaptou a zlib para C#, gerando assim uma versão 100% gerenciada (managed). O resultado está disponível gratuitamente aqui, com uma licença BSD-like (semelhante à da própria zlib).

Para usar a zlib.net, basta copiar o arquivo zlib.net.dll e referenciá-lo no seu projeto.

O coração da zlib.net são as funções de compactação e descompactação com o encapsulamento zlib (o encapsulamento gzip não é suportado), que estão nas classes Deflate e Inflate. A classe ZStream por sua vez encapsula estas duas. Os métodos destas classes são equivalentes às funções que vimos na parte anterior e portanto o código fica muito semelhante:
// Compacta Arquivo
// Usa diretamente a classe Deflate
private void btnCompacta_Click(object sender, EventArgs e)
{
const int bufsize = 30000;
int flush = zlib.zlibConst.Z_NO_FLUSH;
byte[] bufIn = new byte[bufsize];
byte[] bufOut = new byte[bufsize];
FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);
FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);
zlib.ZStream z = new zlib.ZStream();

z.deflateInit(zlib.zlibConst.Z_DEFAULT_COMPRESSION);
do
{
z.avail_in = inFS.Read(bufIn, 0, bufsize);
z.next_in_index = 0;
z.next_in = bufIn;
if (z.avail_in == 0)
flush = zlib.zlibConst.Z_FINISH;
do
{
z.avail_out = bufsize;
z.next_out_index = 0;
z.next_out = bufOut;
z.deflate(flush);
outFS.Write(bufOut, 0, bufsize - z.avail_out);
} while (z.avail_out == 0);
} while (flush != zlib.zlibConst.Z_FINISH);
z.deflateEnd();
outFS.Close();
inFS.Close();
}
A zlib.net implementa ainda uma classe ZOutputStream que deixa o processo de compactação ou expansão transparente, como mostra a rotina abaixo:
// Expande arquivo
// Utiliza ZOutputStream
private void btnExpande_Click(object sender, EventArgs e)
{
int len;
const int bufsize = 30000;
byte[] buffer = new byte[bufsize];
FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFS);
FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);
while ((len = inFS.Read(buffer, 0, bufsize)) > 0)
{
outZStream.Write(buffer, 0, len);
}
outZStream.Flush();
outZStream.Close();
outFS.Close();
inFS.Close();
}
Obs.: para usar ZOutputStream para compactar, especifique o nível de compressão no construtor (o que não é muito intuitivo).

O projeto completo do teste, para o Visual Studio 2005, está aqui.

Nenhum comentário: