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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var ZipFile: TZipFile; begin // Cria uma instância da classe TZipFile ZipFile := TZipFile.Create; try // Indica o diretório e nome do arquivo Zip que será criado ZipFile.Open(GetCurrentDir + '\ArquivosCompactados.zip', zmWrite); // Compacta os arquivos ZipFile.Add('C:\Documento.docx'); ZipFile.Add('C:\Planilha.xlsx'); ZipFile.Add('C:\Apresentacao.pptx'); MessageDlg('Compactação concluída!', mtInformation, [mbOK], 0); finally // Libera o objeto da memória ZipFile.Free; end; end; |
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:
1 2 3 4 5 6 7 8 9 |
var ArquivoSelecionado: string; begin if OpenDialog.Execute then begin for ArquivoSelecionado in OpenDialog.Files do ListBox.Items.Add(ArquivoSelecionado); end; end |
Por conta disso, o método que realiza a compactação sofrerá apenas uma pequena alteração:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var ZipFile: TZipFile; Arquivo: string; begin // Cria uma instância da classe TZipFile ZipFile := TZipFile.Create; try // Indica o diretório e nome do arquivo ZIP que será criado ZipFile.Open(GetCurrentDir + '\ArquivosCompactados.zip', zmWrite); // Percorre os arquivos adicionados na ListBox para compactá-los for Arquivo in ListBox.Items do ZipFile.Add(Arquivo); MessageDlg('Compactação concluída!', mtInformation, [mbOK], 0); finally // Libera o objeto da memória ZipFile.Free; end; end; |
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:
1 |
procedure(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64); |
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.
1 2 3 4 5 6 7 8 9 10 11 12 |
private procedure EventoOnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64); { ... } procedure TForm1.EventoOnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64); begin Application.ProcessMessages; // Exibe a porcentagem de compactação do arquivo Label1.Caption := FormatFloat('#.## %', Position / Header.UncompressedSize * 100); end; |
Agora, claro, precisamos associar o evento no nosso objeto da classe TZipFile:
1 2 3 4 5 6 7 |
// Cria uma instância da classe TZipFile ZipFile := TZipFile.Create; try // Associa o evento OnProgress ZipFile.OnProgress := EventoOnProgress; { ... } |
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
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
private function ObterTamanhoArquivo(const NomeArquivo: string): integer; { ... } function TForm1.ObterTamanhoArquivo(const NomeArquivo: string): integer; var StreamArquivo: TFileStream; begin StreamArquivo := TFileStream.Create(NomeArquivo, fmOpenRead); try result := StreamArquivo.Size; finally StreamArquivo.Free; end; end; |
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.
1 2 3 |
private BytesParaCompactar: integer; BytesProcessados: cardinal; |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
var ZipFile: TZipFile; Arquivo: string; begin BytesParaCompactar := 0; BytesProcessados := 0; // Percorre os arquivos da ListBox para encontrar o total de bytes que será compactado for Arquivo in ListBox.Items do BytesParaCompactar := BytesParaCompactar + ObterTamanhoArquivo(Arquivo); // Cria uma instância da classe TZipFile ZipFile := TZipFile.Create; try // Associa o evento OnProgress ZipFile.OnProgress := EventoOnProgress; // Indica o diretório e nome do arquivo ZIP que será criado ZipFile.Open(GetCurrentDir + '\ArquivosCompactados.zip', zmWrite); // Percorre os arquivos adicionados na ListBox para compactá-los for Arquivo in ListBox.Items do begin ZipFile.Add(Arquivo); // Atualiza a variável que armazena a quantidade de bytes processados BytesProcessados := BytesProcessados + ZipFile.FileInfo[Pred(ZipFile.FileCount)].UncompressedSize; end; MessageDlg('Compactação concluída!', mtInformation, [mbOK], 0); finally // Libera o objeto da memória ZipFile.Free; end; end; |
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.
1 2 3 4 5 6 7 8 9 10 |
procedure TForm1.EventoOnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64); begin Application.ProcessMessages; // Exibe a porcentagem de compactação do arquivo Label1.Caption := FormatFloat('#.## %', Position / Header.UncompressedSize * 100); // Exibe a porcentagem de compactação geral Label2.Caption := FormatFloat('#.## %', (BytesProcessados + Position) / BytesParaCompactar * 100); end; |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
procedure TForm1.EventoOnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64); var PorcentagemArquivo: real; PorcentagemGeral: real; begin Application.ProcessMessages; // Calcula as porcentagens de conclusão PorcentagemArquivo := Position / Header.UncompressedSize * 100; PorcentagemGeral := (BytesProcessados + Position) / BytesParaCompactar * 100; // Atualiza a exibição das porcentagens Label1.Caption := FormatFloat('#.## %', PorcentagemArquivo); Label2.Caption := FormatFloat('#.## %', PorcentagemGeral); // Atualiza as barras de progresso ProgressBar1.Position := Trunc(PorcentagemArquivo); ProgressBar2.Position := Trunc(PorcentagemGeral); end; |
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!
Boa noite amigão, ótimo artigo, como sempre, muito bom, tenho uma dúvida… É possível adicionar senha ao arquivo compactado?
Boa noite, Danilo, como vai?
Ótima pergunta! Até abri o Delphi para conferir. Pelo que analisei até o momento, acredito que não é possível adicionar senha com essa classe nativa, mas vou me aprofundar mais antes de dar uma resposta definitiva.
Abraço!
Também não encontrei, mas vamos que vamos… Abraços e obrigado pela breve resposta
Olha, so passei aqui pra te parabenizar pelo excelente conteúdo disponibilizado pelo blog .
Muito obrigado, Oteniel!
Comentários como o seu me motivam a continuar este trabalho!
Grande abraço!
Utilizo a classa nativa também, muito bom. Parabéns pelo blog.
Olá, Leonardo!
Legal trabalhar com ela, né? 🙂
Obrigado! Abraço!
Parabéns pelo trabalho. Ótimos artigos.
Obrigado, Marcelo!
Continue acompanhado o blog. Abraço!
Muito bom André, muito bom mesmo!
Seria possível compactar sub-diretórios?
Olá, Wanderson, tudo bem?
Sim, é possível compactar diretórios com o método ZipDirectoryContents. O primeiro parâmetro refere-se ao nome do aquivo ZIP que será criado e o segundo parâmetro é o diretório que será compactado. Veja um exemplo:
Abraço!
E como descompactar?
Olá, Marcos. Para descompactar, basta utilizar um dos métodos abaixo conforme a sua necessidade:
Extract
ExtractAll
ExtractZipFile
Abraço!
Muito, meu ajudou muito, parabéns pela sua iniciativa !!!
Muito Obrigado
Opa, eu que agradeço pelo comentário, Cleber!
Abraço!
Olá André. Boa tarde. Uso o Delphi 7. Esta rotina funciona nele?
Uso o Delphi 7 e quando vou executar diz: File not found: vcl.forms.dcu
Olá, Gavel.
A classe
TZipFile
só existe a partir da versão XE2 do Delphi.Nas versões, anteriores, é necessário utilizar componentes de terceiros, como o ZipMaster.
Abraço!
Parabéns, muito útil e pratico. Muito bem explicado.
Obrigado por compartilhar seu conhecimento!
Eu que agradeço pela visita e pelo comentário, Miro! 🙂
Continue acompanhando o blog. Abraço!
Ola
Consigo utilizar no delphi 2009?
Olá, John.
A classe
TZipFile
está disponível somente a partir da versão XE2 do Delphi.No seu caso, uma opção é utilizar componentes de terceiros, como o ZipMaster.
Abraço!
Parabéns pelo blog, estou iniciando meus trabalhos com Delphi (Estagiário haha).
Este artigo me ajudou bastante, porem eu tenho que trabalhar com arquivos zip criptografados, li nos comentários anteriores que esta classe não permitia ate o momento trabalhar com este tipos de arquivos. Gostaria de saber se você já achou alguma solução para o mesmo.
Em minhas pesquisas encontrei algumas informações sobre TPAbbrevia (aparentemente permite fazer isso) e também, este artigo (http://www.uweraabe.de/Blog/2017/03/27/tzipfile-with-password-encryption/) mas com o meu conhecimento em Delphi limitado não pude compreender muito bem.
Aguardo contato.
Olá, Sérgio, tudo bem?
Ainda não tive a necessidade de trabalhar com arquivos ZIP criptografados. De qualquer forma, infelizmente a classe
TZipFile
não oferece mecanismos nativos para encriptação. A alternativa, por enquanto, é buscar componentes de terceiros que possuam essa funcionalidade, embora há indícios de que a classeTZipFile
será aprimorada nas próximas versões.Abraço!
Boa tarde, André. Muito bom seu artigo.
Estou utilizando a classe mas estou tendo problemas com arquivos grandes (maiores que 7GB). A compactação está ficando incompleta, sem dar nenhum erro. Tem notícias de limitações de tamanhos para os arquivos?
Olá, Odlawso, boa noite.
Infelizmente a operação de compressão da classe TZipFile está limitada a arquivos de até 2GB, conforme este tópico da EDN:
https://forums.embarcadero.com/message.jspa?messageID=679217
Neste mesmo tópico, eles sugerem a utilização de componentes de terceiros, como o Abbrevia, ZipForge ou ZipTV para trabalhar com compressão de arquivos grandes.
Abraço!
Aí sim!
\o/
Bom dia, André L. Celestino, poderia mostrar pra gente como descompactar? Até olhei um exemplo de Extract, ExtractAll e ExtractZipFile, mas sem sucesso.
Olá, Bruno, tudo bem?
A descompactação de arquivos com a classe TZipFile não tem muito segredo. Encontrei duas páginas com exemplos simples e claros:
Pointer Cloud
ActiveDelphi
Abraço!
bom dia André L. Celestino eu não entendi onde ele vai buscar pra descompactar e onde ele vai descompactar.
function TForm1.UnZipFile(ArchiveName, Path: String): boolean;
var
Zip: TZipFile;
begin
Zip := TZipFile.Create;
try
Zip.Open(ArchiveName, zmRead);
Zip.ExtractAll(Path);
Zip.Close;
result := True;
except
result := False;
end;
Zip.Free;
end;
Boa tarde, Bruno.
No código que você postou, o método recebe dois parâmetros:
– ArchiveName: arquivo que será descompactado;
– Path: local da descompactação.
Abraço!
André L. Celestino outra duvida como eu posso colocar senha usando o Delphi ao zipar meus arquivos e ao descompactar usando senha ?
Olá, Bruno. Infelizmente a classe TZipFile não traz mecanismos para adicionar senhas ao arquivo compactado.
Para isso, você pode utilizar a biblioteca do TurboPower Abbrevia.
Abraço!
Eu consegui, amigo. Agora preciso de como descompactar com senha.
procedure TForm1.Button1Click(Sender: TObject);
Boa noite, Bruno.
Não tenho conhecimento dos parâmetros de execução do WinRAR.
Sugiro que você leia o manual do próprio aplicativo:
http://acritum.com/software/manuals/winrar/
Tem bastante coisa lá! 🙂
Abraço!
André,
Parabéns pelo artigo.
Gostaria de saber se tenho como verificar se um arquivo que compactei com TZipFile, não está corrompido.
Olá, Marcelo, tudo bem?
Acredito que não é possível fazer essa verificação com a classe
TZipFile
.Uma ideia é abrir o arquivo ZIP logo em seguida e tentar ler o seu conteúdo. Caso ocorra algum erro de leitura, significa que o arquivo não está íntegro.
Abraço!
Boa tarde. Eu uso Delphi Berlin e usei esse seu exemplo para compactar arquivos, porém preciso compactar com senha. Você tem alguma sugestão? eu tentei usar o TZipMaster, coloquei senha mas não zipou com senha. Você tem alguma ideia?
Olá, Maurício, tudo bem?
Infelizmente a classe TZipFile não traz um mecanismo muito fácil para adicionar senha nos arquivos.
Sugiro que você acesse o artigo no link abaixo, no qual o autor apresenta uma forma de adicionar senhas, mas exige uma codificação um pouco extensa:
https://www.uweraabe.de/Blog/2017/03/27/tzipfile-with-password-encryption/
Abraço!
Ola André, tudo blz? Estou fazendo um launcher para game, só que no seu exemplo ele compacta somente arquivos, o que e onde devo alterar em sua fonte para compactar tudo que está em uma pasta, até mesmo subpasta? Tentei modificar seu programa para isso, mas não consegui, teria como me ajudar? Agradeço desde já.
Olá, Pedro, tudo bem?
Boa pergunta! Para compactar diretórios (bem como seus subdiretórios), você pode utilizar o método ZipDirectoryContents da classe
TZipFile
. Veja mais detalhes deste método na documentação da Embarcadero:ZipDirectoryContents
Abraço!
Olá, muito obrigado por me responder, porém dei uma olhada lá e fiquei meio confuso. Você poderia me citar um exemplo de como teria que proceder?
Agora consegui, muito obrigado ^^
Que bom, Pedro!
Eu estava respondendo o seu comentário anterior nesse exato momento, rsrs.
Abraço!
Fiz desta forma…
onde : “ArchivaName = C:\Desenvolvimento\Delphi10.2\newSAVOX\Executavel\Comunicacao\inbox\r99999a.oxf”
Path : “C:\Desenvolvimento\Delphi10.2\newSAVOX\Executavel\Comunicacao\inbox”
Mas está dando um erro. ( Error Reading Zip File)
Ele não extrai mas exclui o arquivo.
Olá, Alesandro, tudo bem?
Verifique se essa extensão “OXF” é um arquivo compactado com a mesma estrutura de um arquivo ZIP.
Digo isso porque a classe
TZipFile
é compatível apenas com arquivos ZIP, ou seja, não consegue processar arquivos com outros motores de compactação.Abraço!
Creio que o arquivo estava corrompido. OXF é só a extensão que alterei após criar, apenas para ficar algo que só o meu sistema vai reconhecer. Mas deu certinho.
Certo, Alesandro! Que bom que conseguiu identificar o problema.
Abraço!
André, consegui e vou deixar para quem tiver a mesma pergunta ^^
Criei a função:
E depois executei ele nessa forma:
Obrigado André. Você sempre faz um ótimo trabalho.
Obrigado pela colaboração, Pedro! 🙂
Tenho certeza que o seu código vai ajudar muitos desenvolvedores, já que é uma necessidade relativamente comum.
Um grande abraço e obrigado pelo feedback!
Bom dia.
Primeiramente parabéns pelo artigo. Muito bom mesmo.
Desculpe mas não encontrei opção de dividir arquivos em tamanho menores. Existe essa possibilidade?
Boa noite, Welder!
Infelizmente não há essa opção de forma nativa no componente.
Abraço!
Parabéns pela explicação clara e objetiva!!!!
Gostaria de saber se tem como compactar uma pasta toda sem ter que selecionar os arquivos uma a um?
Olá, Camillo!
Sim, é possível compactar diretórios com o método ZipDirectoryContents. O primeiro parâmetro refere-se ao nome do aquivo ZIP que será criado e o segundo parâmetro é o diretório que será compactado. Veja um exemplo:
Abraço!
Muito obrigado e mais uma vez parabéns!!!!
Não consigo compactar pastas, dá o erro Acesso Negado.
O que fazer?
Olá, Edson, boa noite.
Este erro pode estar ocorrendo em função da segurança do Windows, ou seja, a sua aplicação não está conseguindo criar o arquivo na pasta indicada.
Experimente executar a sua aplicação como Administrador ou alterar o diretório no qual o arquivo compactado será criado.
Abraço!
Ótima postagem
Obrigado, Francisco!
Bom dia André ! Parabéns pela iniciativa !
Estou tentando compactar várias pastas. Mas são pastas em locais diferentes. Cada vez que executo o ZipDirectoryContents ele sobrescreve o arquivo .zip. Existe uma forma de adicionar e não sobrescrever ?
Um abraço !
Bom dia, Alexandre!
Rapaz, ótima pergunta! Até abri o Delphi para fazer uns testes, mas não encontrei um método que permita compactar vários diretórios de uma vez só. Ao que parece, não é possível.
Uma ideia (que concordo não ser das melhores), é compactar um diretório por vez, gerando arquivos separados. Em seguida, adicionar cada um destes arquivos compactados em um outro arquivo ZIP. Com isso, haverá um arquivo compactado com vários arquivos compactados dentro.
Abraço!
Bom dia, André!
Ao realizar o ExtractZipFile, recebi uma exceção “Invalid argument to date encode.”
Já se deparou com algo semelhante?
Reparei que no .zip em questão há dois arquivos com o mesmo nome. Tanto que realizando a extração pelo WinRAR, o mesmo questiona sobre sobrescrever o arquivo já extraído com o mesmo nome.
Alguma ideia de como proceder neste caso?
Olá, Cleber.
Fiquei curioso com o seu caso. Vou entrar em contato!
Olá André!
Em primeiro lugar, parabéns pelo artigo.
Consegui criar uma rotina de compactação para atender minhas necessidades e funciona perfeitamente, mas para descompactar estou tendo muitos problemas. Sempre dá erro ao executar a função ZipFile.ExtractAll. Não consigo identificar o problema. Será que poderia lhe encaminhar o código pra você dar uma analisada? Qual seria o meio de envio?
Abraços.
Boa noite, Lorival!
Sim, posso analisar o seu código. Vou entrar em contato, ok?
Abraço!
Olá. Gostei do seu artigo. Já li e usei outras sugestões suas e sempre são muito boas e úteis.
Parabéns.
Obrigado, Nelson!
Em breve volto a publicar novos artigos!
Abraço!
Olá André, gostei do artigo, me ajudou a enter o caso.
Estou com uma duvida assim, tenho um código que gera 5 arquivos TXT com nomes diferentes, ficam na mesma pasta, no momento que é gerado estes arquivos já preciso compactar eles, mas não estou conseguindo. Alguma dica?
Olá, Diogo, como vai?
Vou entrar em contato com você para solicitar mais detalhes.
Abraço!
Olá, estou utilizando na para compactar um arquivo no celular, porém ele não cria o zip, o que poderia ser?
Dei uma limada em partes do código que não são necessárias para a possível solução.
Olá, Rai, tudo bem?
Vou entrar em contato com você.
Obs: removi o seu código por questões de privacidade, ok?
Abraço!
Olá André, primeiramente obrigado por compartilhar seus conhecimentos.
Colega, eu estou utilizando o Delphi XE8 e está dando e erro na linha abaixo
A princípio eu achei que estava errando algo no meu fonte, baixei seus fontes de exemplo e apresenta o mesmo erro.
Sabe como posso resolver?
Desde já agradeço.
Obrigado.
Olá, Anderson, bom dia.
Conforme a documentação da Embarcadero, o evento “OnProgress” da classe
TZipFile
está disponível apenas a partir da versão Seattle do Delphi. No XE8 este evento não existe.Abraço!
Ficou muito bom seu artigo André me ajudou muito aqui! Obrigado!
Eu que agradeço pelo comentário, Fernando!
Olá André, primeiro parabéns pelas suas postagens, são sempre muito úteis.
Existe alguma forma de criar um arquivo compactado, particionando em vários volumes?
Por exemplo, eu quero compactar um arquivo grande, dividindo em vários arquivos de até 10Mb. É possível?
Olá, Marco, boa noite!
Primeiramente, obrigado pelo feedback!
Marco, se existe uma forma de criar vários volumes de um mesmo arquivo, infelizmente eu desconheço. Abri o Delphi para conferir as sobrecargas do método “Add”, mas não encontrei nada que se refira ao particionamento de arquivos.
Neste caso, acredito que você terá que utilizar um biblioteca ou um utilitário de terceiros.
Abraço!
Caraca mano, eu ainda não tinha utilizado isso, quebrou um galho danado aqui, valeu mesmo ótimo artigo…
Que bom, Italo!
Essa classe é uma mão na roda mesmo! 🙂
Me ajudou muito. Obrigado.
Eu que agradeço pelo comentário, Anielson!
Boa tarde André, tudo bem??
Estou criando aqui uma forma de compactar arquivos pelo 7Zip, via linha de comando, e cheguei aqui na sua publicação.
Criei um arquivo .bat para execução do comando que eu preciso. Executando o arquivo, executa exatamente o que preciso.
Quando mando executar o .bat pelo Delphi, está retornando um erro dizendo: ‘7z’ não é reconhecido como um comando interno.
Queria saber se poderia descrever como estava usando essa execução pela linha de comando, sem que retornasse erro.
Lembrando que executando o que eu preciso que é o comando (7z a %DirDestino%\%NomeArquivoDestino% %ArquivoOrigem% -v50m), funciona normalmente abrindo o cmd direto ou mesmo executando o .bat fora do Delphi.
Grato pela ajuda e parabéns pelo trabalho!
Olá, Guilherme, tudo bem?
Primeiramente, peço desculpas pela demora.
Guilherme, acredito que, talvez, você terá que indicar o caminho completo do 7z no arquivo .bat, por exemplo:
Outra alternativa é tentar colocar os arquivos do 7z na mesma pasta do executável gerado pelo Delphi. Essa, na verdade, foi a opção que eu usei por muito tempo.
Espero que lhe ajude. Abraço!
Bom dia André, não tem que se desculpar de forma alguma!
Passando aqui apenas para deixar registrado a solução!
Sempre usei a dll “7z.dll” para fazer a compactação dos arquivos nos meus sistemas. Inclusive com um componente para tal. Idem quando usado via linha de comando, fora da minha aplicação. E como você, bastava colocar a dll na pasta do sistema e resolvia.
Porém, no caso desse comando acima, esse passo não funcionou (apenas via meu sistema). Via DOS ou executando o .bat fora do meu sistema, funcionava normalmente.
Aí, resolvi trocar a dll pelo arquivo 7z.exe e funcionou! Não sei se no seu caso usava o .exe mas aqui resolveu assim!
Então só deixar registrado para os demais que cheguem até aqui!
Abraço, obrigado pelo artigo e disponibilidade em ajudar. Tenha um ótimo dia e final de semana!
Olá, Guilherme! Obrigado por retornar ao blog para deixar essa solução!
Eu sempre usei o executável junto com a DLL. Provavelmente é por isso que nunca tive esse problema que você mencionou.
De qualquer forma, que bom que deu certo! 😀
Grande abraço!
Olá André, tudo bem?!
Estou tendo problemas em restaurar arquivos maiores que 4GB. Usando essa classe, o sistema compacta sem erros, mas não restaura os arquivos maiores que 4GB. Você já passou por isso?
Abraço!
Olá, André, como vai?
Nunca fiz o teste de tentar descompactar um arquivo desse tamanho, André.
Vou entrar em contato com você!
Olá, usei seu exemplo como base, ficou perfeito, exceto pelo fato de descobrir mais tarde que o recurso é limitado, não compactando e/ou descompactando arquivos grandes acima de 2GB. Minha pergunta é: será que vão melhorar isso, , de forma a compactar arquivos acima de 2GB? Até o Delphi Rio, ultima versão, continua limitado.
Olá, José Delphino, tudo bem?
Você tem a palavra “Delphi” no sobrenome. Que chique! rsrs
José, pra ser sincero, eu desconheço essa limitação. Vou procurar mais detalhes, inclusive verificar se há alguma novidade sobre isso na versão Sydney (10.4).
Enquanto isso, se você precisar compactar arquivos com mais de 2GB, eu sugiro que use o utilitário do 7-Zip (7z.exe) através de linha de comando.
Abraço!
Boa tarde André, com ZipFile tem como colocar senha na hora de zipar?
Boa tarde, Jhonlemon!
A classe
TZipFile
infelizmente não possui suporte para criar um arquivo compactado com senha. No entanto, há uma possibilidade de essa opção ser adicionada na próxima versão do Delphi 🙂Se você precisa dessa funcionalidade com urgência, sugiro utilizar a DLL do 7-zip.
Abraço!
Boa tarde, André!
Muito bacana sua publicação.
Gostaria de saber se tem como usar o OnProgress quando utilizar ZipDirectoryContents. Eu fiz varios teste aqui sem êxito. Ele não da erro mas nem passa pelo metodo;
Olá, Marcelo, tudo bem?
Ótima pergunta! Eu acessei a documentação do ZipDirectoryContents e notei que o evento OnProgress realmente não está disponível. Ao invés disso, você terá que utilizar um callback chamado ZipProgress (último parâmetro do método ZipDirectoryContents). Neste parâmetro você pode passar uma função que fará a leitura do progresso. Fiz uma pesquisa rápida e encontrei este tópico no StackOverflow com mais detalhes sobre a implementação.
Espero que ajude! Abraço!
Bom dia!
Eu usava outro compactador, usando DLL, resolvi usar este e deu tudo certo.
Didática simples e eficiente, obrigado.
Opa, fico feliz pelo comentário, Antônio.
Abraço!
Tem como dividir o arquivo Zip em vários arquivos de mesmo tamanho?
Olá, Eduardo.
Infelizmente o componente TZipFile não fornece esse mecanismo.
Neste caso, sugiro utilizar o 7-Zip por linha de comando.
Abraço!
André meu mestre, não e a primeira vez que te peço dicas, me desculpa mais uma vez e obg pelas outras vezes, rsrsrsr… vamos lá, com esse ZipFile tem como ler um arquivo especifico que esta dentro do “.zip” , pegar as informações sem ter que descompactar o arquivo “.zip” ???
Olá, Moises, boa noite!
Rapaz, boa pergunta. Eu acredito que com o TZipFile não é possível. Essa classe foi disponibilizada somente para compactar/extrair arquivos.
Talvez bibliotecas ou utilitários de terceiros possam ter essa funcionalidade. Eu estiver olhando, por exemplo, as linhas de comando do 7-Zip. O mais próximo que encontrei foi o comando “List”, mas acredito que o propósito é apenas listar os arquivos.
Abraço!