zip

Embora não represente um tipo de demanda tão comum, por vezes surgirão situações em que aplicações de software precisarão fazer uso de mecanismos de compactação na manipulação de arquivos. Dentre os os motivos que contribuem para a adoção de tal prática, merece destaque a necessidade em se economizar recursos no armazenamento e/ou transmissão de dados dos quais um software depende.

Um dos formatos de compactação mais populares é, sem sombra de dúvidas, o padrão ZIP. Embora conte com suporte a este formato desde a versão 2.0, foi com a classe ZipFile disponibiliza a partir do .NET Framework 4.5 que a implementação de funcionalidades de compactação se tornou uma tarefa mais simples. Maiores detalhes a respeito do uso do tipo ZipFile podem ser encontrados no link a seguir:

http://www.devmedia.com.br/manipulacao-de-arquivos-zip-no-net-framework-4-5/26284

Além do tipo ZipFile do .NET Framework, existem outras opções que podem ser utilizadas em soluções que dependam de arquivos no formato ZIP. Uma delas seria a biblioteca SharpZipLib, a qual oferece desde a versão 1.1 da plataforma .NET meios para a gravação e leitura de arquivos .zip. Maiores informações a respeito desta solução podem ser obtidos através do link:

http://www.sharpziplib.com/

Os recursos oferecidos pelo projeto SharpZipLib representam uma interessante alternativa para a manipulação de arquivos compactados, sobretudo em projetos legados em que se tornar necessária a implementação de funcionalidades baseadas no padrão ZIP.

O objetivo deste artigo é discutir o uso do SharpZipLib em aplicações .NET, demonstrando de que forma esta biblioteca pode ser empregada na compactação e descompactação de arquivos .zip.

Exemplos de uso da biblioteca SharpZipLib

A biblioteca SharpZipLib pode ser adicionada a um projeto .NET por meio do utilitário NuGet. Na Imagem 1 é possível observar um exemplo disto, com a adição de uma referência em um projeto do Visual Studio 2013.

Imagem01
Imagem 1: Adicionando a biblioteca SharpZipLib a um projeto no Visual Studio 2013

O primeiro exemplo detalhando o uso do SharpZipLib envolverá a compactação das planilhas apresentadas na Imagem 2. A ideia é gerar um arquivo compactado com estes itens separados em pastas, com cada uma destas últimas correspondendo a um mês específico.

Imagem02
Imagem 2: Arquivos a serem compactados como teste

Uma das formas de efetuar a compactação de arquivos a partir da biblioteca SharpZipLib é utilizando instâncias da classe ZipFile (namespace ICSharpCode.SharpZipLib.Zip). A Listagem 1 demonstra o uso deste tipo na compactação dos arquivos citados nesta seção.

Conforme é possível observar, o processo de compactação de arquivos através do SharpZipLib envolve:

  • A criação de uma instância do tipo ZipFile, com isto acontecendo a partir de uma chamada ao método Create definido nesta classe;
  • A invocação do método BeginUpdate, a fim de iniciar o preenchimento do arquivo .zip com os itens que farão parte deste último;
  • Chamadas ao método Add, a fim de incluir cada planilha a ser compactada dentro do arquivo .zip. Esta operação recebe como parâmetros o caminho completo do item a ser compactado, além de um caminho relativo a ser gerado dentro do arquivo.zip e no qual poderá ou não ser especificada uma estrutura de diretórios (neste exemplo específico está sendo criada uma pasta para cada mês);
  • A realização de chamadas ao métodos CommitUpdate e Close, de forma a confirmar as alterações realizadas no arquivo .zip e desalocar o uso do mesmo ao fim deste procedimento.

A execução desse conjunto de instruções produzirá como resultado o arquivo Exemplo.zip, conforme indicado na Imagem 3.

string dirArquivosACompactar =
    @"C:\Temp\TesteCompactacao\ArquivosACompactar\";

using (ZipFile arquivoZip =
    ZipFile.Create(@"C:\Temp\TesteCompactacao\Exemplo.zip"))
{
    arquivoZip.BeginUpdate();

    arquivoZip.Add(dirArquivosACompactar + "Despesas - 03-2014.xls",
        @"\03-2014\Despesas - 03-2014.xls");
    arquivoZip.Add(dirArquivosACompactar + "Receitas - 03-2014.xls",
        @"\03-2014\Receitas - 03-2014.xls");
    arquivoZip.Add(dirArquivosACompactar + "Despesas - 04-2014.xls",
        @"\04-2014\Despesas - 04-2014.xls");
    arquivoZip.Add(dirArquivosACompactar + "Receitas - 04-2014.xls",
        @"\04-2014\Receitas - 04-2014.xls");

    arquivoZip.CommitUpdate();
    arquivoZip.Close();
}

Listagem 1: Exemplo de compactação de arquivos

Imagem03
Imagem 3: Arquivo zip gerado a partir da biblioteca SharpZipLib

Já a Listagem 2 apresenta um conjunto de instruções que permitem descompactar o arquivo gerado no passo anterior. A realização deste tipo de tarefa engloba:

  • A geração de uma instância do tipo FileStream (namespace System.IO), a partir da qual ocorrerá a leitura do conteúdo do arquivo .zip;
  • A criação de uma instância baseada na classe ZipFile, baseando-se para isto na referência do tipo FileStream gerada anteriormente;
  • Um array de bytes também é gerado (variável “buffer”), com esta estrutura sendo posteriormente utilizada na descompactação de arquivos;
  • Um loop foreach é então iniciado, de forma a se obterem instâncias do tipo ZipEntry (namespace ICSharpCode.SharpZipLib.Zip), acessando para isto a referência da classe ZipFile. Será a partir destes objetos do tipo ZipFile que os diferentes itens que fazem parte de um arquivo .zip serão descompactados;
  • Uma das checagens efetuadas dentro do loop foreach verifica, através da propriedade IsFile, se o objeto ZipEntry acessado num determinado momento corresponde ou não  a um arquivo (instâncias do tipo ZipEntry também são utilizadas para representar diretórios compactados em um arquivo .zip);
  • A propriedade Name da classe ZipEntry contém o caminho relativo de um arquivo, ou seja, seu nome e o local em que o mesmo se encontra armazenado dentro do arquivo .zip considerado. O valor associado a tal propriedade servirá de base que o processo de descompactação crie as pastas e grave os arquivos encontrados no local correto;
  • A classe Path (namespace System.IO) está sendo empregada na manipulação do caminho em que um arquivo será descompactado (através dos método Combine e GetDirectoryName). É possível notar também o uso da classe Directory (namespace System.IO), sendo que a partir desta última será gerada a estrutura de diretórios para o processo de descompactação;
  • A última etapa para a descompactação envolve a obtenção de uma instância da classe Stream (namespace System.IO), invocando para isto o método GetInputStream a partir da referência da classe ZipFile criada anteriormente. Na sequência é gerado um objeto do tipo FileStream; tal referência, o array de bytes e a instância da classe Stream são então repassadas como parâmetros à operação Copy, definida na classe StreamUtils (namespace ICSharpCode.SharpZipLib.Core). O método Copy será responsável por descompactar cada item contido em um arquivo .zip;
  • Por fim, os objetos dos tipos ZipFile e FileStream criados no início do processo são desalocados. No caso específico de ZipFile, configurar o valor da propriedade IsStreamOwner como true possibilita que outras referências criadas através da biblioteca SharpZipLib também sejam liberadas.
string caminhoBaseOrigem = @"C:\Temp\TesteDescompactacao\";

using (FileStream fs = File.OpenRead(
    @"C:\Temp\TesteCompactacao\Exemplo.zip"))
{
    ZipFile arquivoZip = null;
    try
    {
        arquivoZip = new ZipFile(fs);
        String caminhoRelativoArquivo;
        string caminhoDescompactacao;
        string caminhoArquivoASerDescompactado;
        byte[] buffer = new byte[4096];

        foreach (ZipEntry zipEntry in arquivoZip)
        {
            if (!zipEntry.IsFile)
                continue;

            caminhoRelativoArquivo = zipEntry.Name;
            caminhoArquivoASerDescompactado =
                Path.Combine(caminhoBaseOrigem, caminhoRelativoArquivo);
            caminhoDescompactacao =
                Path.GetDirectoryName(caminhoArquivoASerDescompactado);

            if (caminhoDescompactacao.Length > 0 &&
                !Directory.Exists(caminhoDescompactacao))
                Directory.CreateDirectory(caminhoDescompactacao);

            Stream zipStream = arquivoZip.GetInputStream(zipEntry);
            using (FileStream streamWriter =
                File.Create(caminhoArquivoASerDescompactado))
            {
                StreamUtils.Copy(zipStream, streamWriter, buffer);
            }
        }
    }
    finally
    {
        if (arquivoZip != null)
        {
            arquivoZip.IsStreamOwner = true;
            arquivoZip.Close();
        }
    }

    fs.Close();
}

Listagem 2: Exemplo de descompactação de arquivos

Na Imagem 4 está toda a estrutura com diretórios e arquivos gerados após a execução das instruções que contam na Listagem 2.

Imagem 4
Imagem 4: Arquivos descompactados com a biblioteca SharpZipLib

Conclusão

Procurei apresentar neste artigo uma alternativa para a manipulação de arquivos .zip em projetos .NET. Conforme mencionado aqui, a biblioteca SharpZipLib pode se revelar como um recurso extremamente útil em projetos criados em versões mais antigas do .NET Framework.

Espero que o conteúdo aqui abordado possa lhe ser útil. Até uma próxima oportunidade!

 


Renato Groffe

Atua como consultor em atividades voltadas ao desenvolvimento de softwares há mais de 13 anos. Bacharel em Sistemas de Informação, com especialização em Engenharia de Software. Microsoft Certified Technology Specialist (Web, WCF, Distributed Applications, ADO.NET, Windows Forms), Microsoft Specialist (HTML5 with JavaScript and CSS3, Developing ASP.NET MVC 4 Web Applications), Oracle Certified Associate (PL/SQL), Sun Certified (SCJP, SCWCD), ITIL Foundation V2, Cobit 4.1 Foundation.

Facebook Google+ 

Comentários

comentarios