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:
  1. // Compacta Arquivo  
  2. // Usa diretamente a classe Deflate  
  3. private void btnCompacta_Click(object sender, EventArgs e)  
  4. {  
  5.    const int bufsize = 30000;  
  6.    int flush = zlib.zlibConst.Z_NO_FLUSH;  
  7.    byte[] bufIn = new byte[bufsize];  
  8.    byte[] bufOut = new byte[bufsize];  
  9.    FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);  
  10.    FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);  
  11.    zlib.ZStream z = new zlib.ZStream();  
  12.   
  13.    z.deflateInit(zlib.zlibConst.Z_DEFAULT_COMPRESSION);  
  14.    do  
  15.    {  
  16.        z.avail_in = inFS.Read(bufIn, 0, bufsize);  
  17.        z.next_in_index = 0;  
  18.        z.next_in = bufIn;  
  19.        if (z.avail_in == 0)  
  20.            flush = zlib.zlibConst.Z_FINISH;  
  21.        do  
  22.        {  
  23.            z.avail_out = bufsize;  
  24.            z.next_out_index = 0;  
  25.            z.next_out = bufOut;  
  26.            z.deflate(flush);  
  27.            outFS.Write(bufOut, 0, bufsize - z.avail_out);  
  28.        } while (z.avail_out == 0);  
  29.    } while (flush != zlib.zlibConst.Z_FINISH);  
  30.    z.deflateEnd();  
  31.    outFS.Close();  
  32.    inFS.Close();  
  33. }  
A zlib.net implementa ainda uma classe ZOutputStream que deixa o processo de compactação ou expansão transparente, como mostra a rotina abaixo:
  1. // Expande arquivo  
  2. // Utiliza ZOutputStream  
  3. private void btnExpande_Click(object sender, EventArgs e)  
  4. {  
  5.    int len;  
  6.    const int bufsize = 30000;  
  7.    byte[] buffer = new byte[bufsize];  
  8.    FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);  
  9.    zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFS);  
  10.    FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);  
  11.    while ((len = inFS.Read(buffer, 0, bufsize)) > 0)  
  12.    {  
  13.        outZStream.Write(buffer, 0, len);  
  14.    }  
  15.    outZStream.Flush();  
  16.    outZStream.Close();  
  17.    outFS.Close();  
  18.    inFS.Close();  
  19. }  
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: