[Delphi] Compactação de arquivos com a classe nativa TZipFile

Olá, amigos! Tudo bem?
Acredito que vocês já tiveram que usar componentes de terceiros ou utilitários externos para trabalhar com compactação de arquivos no Delphi, não é?
Bom, eles não são mais necessários. Acompanhe, neste artigo, um pequeno tutorial sobre como trabalhar com a classe TZipFile nativa do Delphi exibindo, inclusive, o andamento da compactação em uma barra de progresso!

Introdução

Se recordo bem, na época em que trabalhava com Delphi 7, eu utilizava um componente third-party chamado TZipMaster para compactação de arquivos através da aplicação. Quando migrei o meu projeto para o Delphi XE3, decidi utilizar a ferramenta 7z (7-Zip) via linha de comando através do Delphi, principalmente para evitar a instalação de componentes de terceiros.

Porém, mesmo que o 7-Zip tenha funcionado, não me atentei que o Delphi trazia uma classe nativa para trabalhar com compactação de arquivos desde a versão XE2, chamada TZipFile. Imediatamente fiz alguns testes com essa classe e os resultados foram bem positivos, me incentivando a usá-la a partir daquele momento.

Na versão Seattle, a classe TZipFile recebeu o evento OnProgress, exclusivo para trabalhar com o status da compactação em tempo real, fornecendo as seguintes informações:

  • Nome do arquivo
  • Cabeçalho com informações adicionais do arquivo
  • Bytes processados

Com este evento, é possível, por exemplo, exibir a porcentagem ou uma barra de progresso enquanto os arquivos são compactados. Interessante, não?

Exemplo de codificação com TZipFile

Bom, melhor apresentar tudo isso na prática! Mãos à obra!
Trabalhar com a classe TZipFile é bem, bem fácil. Primeiro, é necessário declarar o namespace System.Zip na seção uses. Depois, basta instanciar um objeto da classe para definir os dados e executar a compactação:

Pronto, pessoal! Não tem segredo, né? 🙂

Porém, não paramos por aqui. Agora, partiremos para a parte mais interessante, que são os aprimoramentos!

Dica #1: Adicionar arquivos de forma dinâmica

Claro, não deixaremos os nomes dos arquivos fixos no código-fonte. O correto é permitir que o usuário possa adicionar os arquivos que deseja compactar. Para isso, utilizaremos o componente TOpenDialog, da paleta Dialogs, configurando a propriedade Options > ofAllowMultiSelect para True, de forma que o usuário possa selecionar vários arquivos de uma só vez. Adicionaremos também um componente TListBox para apresentar os arquivos selecionados.

O código para adicionar arquivos terá a seguinte codificação:

Por conta disso, o método que realiza a compactação sofrerá apenas uma pequena alteração:

Dica#2: Exibir a porcentagem de compactação do arquivo

Lembram-se do evento OnProgress? Utilizaremos ele nessa dica para fornecer um feedback visual do progresso da compactação.

O método que associaremos a este evento é do tipo TZipProgressEvent e deve obrigatoriamente obedecer à seguinte assinatura de parâmetros:

O primeiro parâmetro é o objeto chamador do evento que, neste caso, sempre será um objeto da classe TZipFile. O segundo parâmetro refere-se ao nome do arquivo atualmente em processo de compactação. O terceiro parâmetro é um objeto da classe TZipHeader que carrega informações de cabeçalho do arquivo, como o tamanho, CRC, método de compressão e outros dados. Por fim, o quarto parâmetro indica a quantidade de bytes que já foram processados durante a compactação.

Para o nosso exemplo, codificaremos o método abaixo no formulário, considerando que Label1 será o componente que irá exibir a porcentagem. A matemática é simples: dividimos a quantidade de bytes processados pelo tamanho total do arquivo e, em seguida, multiplicamos por 100 para encontrar a porcentagem.

Agora, claro, precisamos associar o evento no nosso objeto da classe TZipFile:

Dica #3: Exibir a porcentagem de compactação geral

Se existirem dois ou mais arquivos, a porcentagem que codificamos acima irá reiniciar para cada compactação. Seria interessante, então, se houvesse uma porcentagem para indicar o progresso geral de compactação. Pois bem, é isso que faremos!

Primeiramente, precisamos da soma do tamanho de todos os arquivos que serão compactados para usá-la no cálculo do progresso geral. Codificaremos um método que usa um objeto da classe TFileStream para acessar a função Size:

Em segundo lugar, será necessário também declarar duas variáveis de classe: uma para armazenar o tamanho de todos os arquivos e outra para manter a quantidade de bytes já processados. Compreendo que temos o parâmetro Position do evento OnProgress, mas lembre-se que ele é reiniciado para cada arquivo. Vale ressaltar também que essas duas variáveis são declaradas com esse escopo porque serão referenciadas em diferentes métodos.

O próximo passo é adicionar algumas linhas no método principal de compactação. Atente-se que na iteração dos itens da ListBox foi adicionada uma nova instrução para atualizar a variável BytesProcessados ao término de cada compactação. Isso é necessário para que o cálculo da porcentagem geral considere os arquivos anteriores já compactados.

No evento OnProgress, por sua vez, também adicionaremos uma linha para atualizar o componente que exibirá a porcentagem geral, seguindo o mesmo contexto matemático.

Dica #4: Barras de progresso!

Acharam que eu esqueceria? As barras de progresso são as mais importantes! 🙂
Navegue até a aba Win32 na paleta e adicione dois componentes TProgressBar no formulário. No código-fonte, a única alteração será no evento OnProgress para atualizar estes componentes. Além disso, já que utilizaremos os mesmos cálculos tanto para a porcentagem quanto para a barra de progresso, é mais prudente armazenar o resultado dos cálculos em variáveis:

And we’re done!
Isso é o que tenho para mostrar hoje, pessoal.
Para ajudá-los, segue abaixo o link para download do projeto de exemplo deste artigo, contendo algumas melhorias:

Download do projeto de exemplo de compactação de arquivos

Lembrem-se: qualquer dúvida, sugestão ou observação, deixem um comentário!
Até a próxima!


André Celestino