Compactação de arquivos com a classe TZipFile
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRgNCiI0PU7Sttfzp9SZZUhMJkBWsxGgUa7Wt90aMdfXt5cVIGfWxeeJDbYxwe80wGX4aAv5uBA2augvhBb8MDnYuS7mlTIboARxSkoOfsLpgWfPWUVqe0wwuAHoO22q0CcUPcwq4Cn6E/s200/05555.png)
Com esta classe podemos compactar, descompactar, abrir e fechar um arquivo ".zip"
Vamos testar a classe TZipFile. Antes de qualquer coisa declare a System.Zip nas uses do Form.
Em nosso exemplo vamos fazer o compactar/descompactar de vários arquivos que iremos selecionar pelo próprio sistema.
Vamos utilizar:
O TForm ira ficar mais ou menos semelhante a este
Para poder selecionar vários arquivos no TOpenDialog temos a configuração propriedade >> Options >> ofAllowMultiSelect colocamos "True".
Abaixo um controle para habilitar os botões para não precisar fazer validação de preenchimento na hora do compactamento
Abaixo um controle para habilitar os botões para não precisar fazer validação de preenchimento na hora do compactamento
procedure TFSistema.ControlesEnabled;
begin
sbArquivoZip.Enabled := lbListagem.Count > 0;
BtnCompactar.Enabled := sbArquivoZip.Enabled and (Trim(EditArquivoZip.Text) <> EmptyStr);
BtnDescompactar.Enabled := sbArquivoZip.Enabled;
end;
Para adicionar/remover os aquivos para serem utilizados vamos colocar o código:
procedure TFSistema.BtnProcurarClick(Sender: TObject);
var
lDirectory: string;
begin
if OpenDialog.Execute then begin {Adicionar na listagem}
for lDirectory in OpenDialog.Files do
lbListagem.Items.Add(lDirectory);
ControlesEnabled;
end;
end;
procedure TFSistema.BtnRemoverClick(Sender: TObject);
begin
lbListagem.Items.Delete(lbListagem.ItemIndex); {Remover da listagem}
ControlesEnabled;
end;
Para selecionar o caminho e o nome do arquivo que será salvo (arquivo compactado);
procedure TFSistema.sbArquivoZipClick(Sender: TObject);
begin
SaveDialog.InitialDir := GetCurrentDir;
if SaveDialog.Execute then
EditArquivoZip.Text := SaveDialog.FileName;
ControlesEnabled;
end;
No componente TSaveDialog vamos mudar as propriedades;
- DefaultExt = 'zip'
- FileName = 'ArquivosNovo'
- Filter = 'Arquivo ZIP|*.zip'
Vamos fazer um evento que irá mostrar as porcentagens de quanto falta a finalização da compactação:
procedure TFSistema.OnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64);
var
lPercentualArquivo, lPercentualGeral: Real;
begin
Application.ProcessMessages;
lbArquivosUtilizados.Caption := ExtractFileName(FileName);
lPercentualArquivo := Position / Header.UncompressedSize * 100;
lbArquivo.Caption := FormatFloat('#.## %', lPercentualArquivo);
pbTempoArquivo.Position := Trunc(lPercentualArquivo);
lPercentualGeral := (FBytesConcluido + Position) / FBytesTotal * 100;
lbTempoAproximado.Caption := FormatFloat('#.## %', lPercentualGeral);
pbTempoAproximado.Position := Trunc(lPercentualGeral);
end;
A variável lbArquivosUtilizados erá mostrar o nome dos aquivos já compactados e o Status "pbTempoAproximado" mostra o quanto dele foi compactado.
Já o label "lbArquivo" esta recebendo o percentual total que esta sendo compactado e o "pbTempoArquivo" mostra através do StatusBar a mesma informação.
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.
private
{ Private declarations }
FBytesTotal, FBytesConcluido: Cardinal;
Agora vamos calcular a quantidade total de arquivos que será compactados;
function TFSistema.QuantidadeTotal: integer;
var
lArquivo: string;
begin
Result := 0;
for lArquivo in lbListagem.Items do
Result := Result + TamanhoArquivo(lArquivo);
end;
E um que ira verificar o tamanho dos arquivos;
function TFSistema.TamanhoArquivo(const AArquivo: string): integer;
var
lStream: TFileStream;
begin
lStream := TFileStream.Create(AArquivo, fmOpenRead);
try
Result := lStream.Size;
finally
lStream.Free;
end;
end;
Agora vamos para o código de compactação, primeiro passo e verificar se contem arquivo para compactar, coloquei um checkBox também para decidir se irá abrir novamente apos a compactação ou não.
Utilizaremos um laço de repetição for para poder passar em todos os arquivos adicionados no ListBox e adicionamos no lZipFile.Add. Isto fará com que de para adicionar mais de um arquivo ao mesmo tempo.
procedure TFSistema.BtnCompactarClick(Sender: TObject);
var
lZipFile: TZipFile;
lArquivo: string;
begin
FBytesConcluido := 0;
FBytesTotal := QuantidadeTotal;
lZipFile := TZipFile.Create;
try
lZipFile.Open(SaveDialog.FileName, zmWrite);
lZipFile.OnProgress := OnProgress;
for lArquivo in lbListagem.Items do begin
lZipFile.Add(lArquivo);
FBytesConcluido := FBytesConcluido + lZipFile.FileInfo[Pred(lZipFile.FileCount)].UncompressedSize;
end;
if FileExists(SaveDialog.FileName) then begin
MessageDlg('Processo concluído!', mtInformation, [mbOK], 0);
if chAbrirAposCompactacao.Checked then
ShellExecute(0, nil, PChar(SaveDialog.FileName), nil, nil, SW_SHOWNORMAL);
end;
finally
lZipFile.Free;
end;
end;
Para ter o descompactamento do arquivo temos o código a seguir, coloquei um código bem simples reaproveitando os campos a cima
procedure TFSistema.BtnDescompactarClick(Sender: TObject);
var
lUnZipper: TZipFile;
begin
if OpenDialog.Execute then begin {Adicionar na listagem}
lUnZipper := TZipFile.Create;
try
lUnZipper.Open(OpenDialog.FileName, zmRead);
lUnZipper.ExtractAll(ExtractFilePath(EditArquivoZip.Text));
lUnZipper.Close;
finally
FreeAndNil(lUnZipper);
end;
end;
end;
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQE0mvMK8QmSArnBMOQ6-U3_Oy8Vk99hPJYvhMWG0cmXr-X8YoQ07W0kUwNOM6H_8tpR4F2YCf9-FTsJTwaTiE0ZCdjljYp3QZKLrRlNxD5rOO8322Ahpy8BvDl2NC_KjUq89llrPsnxw/s640/0202.gif)
Exemplo: Download do exemplo
Nossa muito legal. Não sabia, ou nem me passava pela cabeça que o delphi tinha a biblioteca de compactação em System.Zip. Já vou tirar um componente véio que eu tinha. Agora fica tudo mais fácil. Obrigado por compartilhar o código. Assim torna mais rápido pra mim a migração. Grato de coração.
ResponderExcluirSaudações!
ResponderExcluirEu utilizei essa classe e realmente substitui todos os componentes de terceiros por um nativo, porém eu tive um problema que me forçou a retornar para o componente de terceiros, ao compactar um arquivo XML bem pequeno o arquivo ZIP ficava extremamente grande, maior que o arquivo compactado, exemplo o arquivo xml tinha 6k e o arquivo zipado ficava com 35Mega, o que gerou problemas em clientes com internet fraca..
Porém eu gostei muito de usar o TZipFile e não gostaria de abandona-lo, você sabe o que eu deixei de fazer para acontecer essa anomalia, e para piorar no computador de desenvolvimento não acontece, somente no cliente para variar....
Grato!
Tem um exemplo para pasta?
ResponderExcluirTem como Compactar o arquivo dividindo em arquivos menores?
ResponderExcluirTem como Compactar e dividir o arquivos em arquivos menores? Se sim tem um Exemplo?
ResponderExcluirComo seria para Dividir em varios arquivos de 10Mb por exemplo?
ResponderExcluir