Começando

Se você ainda, não teve de implementar uma rotina que comprima arquivos dentro do software que você está desenvolvendo com certeza uma hora essa necessidade aparecerá, porém felizmente para nós programadores iniciantes ou não a maioria das linguagens já possui alguma biblioteca que nos ajuda bastante com isso. No caso do delphi 7, á biblioteca utilizada e a Zlib que implementa um algoritmo de compressão de mesmo nome. Este algoritmo já é um padrão para a compressão de arquivos, sendo utilizados por diversos sistemas operacionais, e presente inclusive no Kernel do Linux. Há vários componentes hoje disponíveis em delphi que podem estar trabalhando a compressão de arquivos, mas eles não serão abordados.

 

Antes vamos conceituar um pouco

 A compressão de dados nada mais é que a redução de dados ocupados por determinado arquivo em um dispositivo, normalmente é realizada por algum algoritmo, que consegue reduzir significativamente a quantidades de bits de um dado, podendo ser uma imagem, um texto ou outro arquivo qualquer.

Podemos estar classificando a forma de compressão em “Compressão sem perda” e “Compressão com perda”. Uma compressão sem perda ocorre quando ao descomprimir obtemos dados idênticos aos que tínhamos antes da compressão. Já a compressão com perda, ocorre quando o algoritmo utilizado elimina algumas informações redundantes a um determinado arquivo, esse tipo de compressão é bem comum em digitalizações de imagens.

            O Zlib utiliza um método de compressão sem perdas, ou seja, obteremos um arquivo idêntico após a descompressão do arquivo. Um ponto importante, é não confundir compressão com compactação, resumidamente uma reduz o tamanho e a outra forma uni dados que por ventura estão desunidos. Como por exemplo, a desfragmentação de arquivos presentes no Windows.

 

Um exemplo bem didático

Bem, depois de um pouco de informação, vamos a um exemplo didático utilizando está fantástica biblioteca já presente no delphi 7.

Primeiramente vamos definir um novo projeto no delphi com o nome de CompZlib, criar um novo formulário e organizar os seguintes componentes:

1.      Um label;

2.      Dois botões com os captions “Selecionar” e “Comprimir” respectivamente;

3.      Um listbox;

4.      Um opendialog.

Não esqueça de chamar a Zlib no inicio do projeto, nas Uses.

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls,Zlib;

 

No botão “selecionar” insira o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);

begin

     if OpenDialog_1.Execute then ListBox_1.Items.Add(OpenDialog_1.FileName);

end;

            No botão “comprimir” insira o seguinte código:

procedure TForm1.btnCompClick(Sender: TObject);

Var

   Nome : String;

begin

     Nome := RemoveExtensao(ExtractFileName(ListBox_1.Items.Text));

      Comprimir(ExtractFilePath(ListBox_1.Items.Text)+Nome+'.Zip',[ExtractFilePath(ListBox_1.Items.Text)+Trim(ExtractFileName(ListBox_1.Items.Text))]);

end;

 

Agora vamos à função que irá comprimir o arquivo efetivamente, criaremos uma procedure chamada “comprimir” que será invocada no evento “Click” do botão, e ela receberá como parâmetro o nome do arquivo e a extensão que desejo utilizar e um Array de String contendo o arquivo(S) que desejo comprimir.

 

procedure Comprimir(ArquivoCompacto: TFileName; Arquivos: array of TFileName);

var

  FileInName: TFileName;

  FileEntrada, FileSaida: TFileStream;

  Compressor: TCompressionStream;

  NumArq, I, Len, Size: Integer;

  Fim: Byte ;

begin

     FileSaida := TFileStream.Create(ArquivoCompacto, fmCreate or fmShareExclusive);

     Compressor := TCompressionStream.Create( clMax, FileSaida);

     NumArq := Length(Arquivos);

     Compressor.Write(NumArq, SizeOf(Integer));

     try

        for I := Low(Arquivos) to High(Arquivos) do begin

           FileEntrada := TFileStream.Create(Arquivos[I], fmOpenRead and fmShareExclusive);

           try

              FileInName := ExtractFileName(Arquivos[I]);

              Len := Length(FileInName);

              Compressor.Write(Len, SizeOf(Integer));

              Compressor.Write(FileInName[1], Len);

              Size := FileEntrada.Size;

              Compressor.Write(Size, SizeOf(Integer));

              Compressor.CopyFrom(FileEntrada, FileEntrada.Size);

              Fim := 0;

              Compressor.Write(Fim, SizeOf(Byte));

              finally

              FileEntrada.Free;

          end;

        end;

       finally

      FreeAndNil(Compressor);

      FreeAndNil(FileSaida);

     end;

end;

 

Bem está é a implementação de um exemplo de compressão de arquivos utilizando a biblioteca Zlib no Delphi 7, como observado o Zlib trabalha na compressão de uma Stream (seqüência de bytes), ou seja, ela comprimi o arquivo desejado, reduzindo consideravelmente o tamanho total dos bytes.

Agora que comprimimos o nosso arquivo, como saberemos se a operação foi realizada com sucesso? Bem para isso vamos também implementar uma procedure de descompressão, que seguindo os passos iniciais poderemos fazer um outro projeto que possua um botão de descompressão, abaixo a procedure.

 

procedure Descomprimir(ArquivoZip: TFileName; DiretorioDestino: string);

var

   NomeSaida: string;

   FileEntrada, FileOut: TFileStream;

   Descompressor: TDecompressionStream;

   NumArq, I, Len,Size: Integer;

   Fim: Byte;

begin

     FileEntrada := TFileStream.Create(ArquivoZip, fmOpenRead and fmShareExclusive);

     Descompressor := TDecompressionStream.Create(FileEntrada);

     Descompressor.Read(NumArq,SizeOf(Integer));

     try

        I:=0;

        While I < NumArq  do begin

           Descompressor.Read(Len,SizeOf(Integer));

           SetLength(NomeSaida, Len);

           Descompressor.Read(NomeSaida[1],Len);

           Descompressor.Read(Size,SizeOf(Integer));

           FileOut := TFileStream.Create(IncludeTrailingBackslash(DiretorioDestino) + NomeSaida, fmCreate or fmShareExclusive);

           try

              FileOut.CopyFrom(Descompressor,Size);

              finally

              FileOut.Free;

           end;

           Descompressor.Read(Fim, SizeOf(Byte));

           Inc(I);

        end;

        finally

        FreeAndNil(Descompressor);

        FreeAndNil(FileEntrada);

  end;

end;

 

Bem como na compressão, a descompressão também é realizada trabalhando - se com Stream que são lidas e montadas em arquivos do tipo TFileStream que serão salvas no diretório destino que é informado a procedure. Uma observação importante neste exemplo é que ao comprimir usando um TCompressionStream só conseguiremos descomprimir utilizando um TDecompressionStream, todavia as taxas de compressão são impressionantes e bastantes .

           Seja para realizaçaõ de alguma rotina de backup ou transmissão de vários arquivos via rede comprimir e descomprimir pode ser uma otima solução.
 
Abraços a todos...
 
 

Referências

Para alguém que pode estar atrás de mais conceitos e informações a bibliografia e webgrafias ajudaram a compor este pequeno artigo:

 

http://informatica.hsw.uol.com.br/compressao-de-arquivos.htm (Acesso: 20/04/2009)

http://pt.wikipedia.org/wiki/Compressão_de_dados  ( Acesso : 20/04/2009)

CANTÚ,Marcos. Dominando o Delphi 2005 . 2. Pearson –  São Paulo, 2006.