Compactar com zLib
Galera alguem sabe como compactar mais de um arquivo juntando em apenas um usando zLib.pas?
Valew..
Valew..
Madrick
Curtidas 0
Respostas
Madrick
22/03/2005
Galera ninguem tem uma ideia naum?
GOSTEI 0
Madrick
22/03/2005
Galera, como não consegui resposta para minha duvida, eu acho que consegui compactar mais de um arquivo com o zlib, ficou tipo assim:
procedure TForm1.Button1Click(Sender: TObject);
var
FileIni,FileIni2, FileOut: TFileStream;
Zip: TCompressionStream;
begin
FileIni := TFileStream.Create(´C:\Delivery\arquivo1´, fmOpenRead and fmShareExclusive);
FileIni2 := TFileStream.Create(´C:\Delivery\arquivo2, fmOpenRead and fmShareExclusive);
FileOut:=TFileStream.Create(´C:\Delivery\ArqCompact.arq´, fmCreate or fmShareExclusive);
Zip:=TCompressionStream.Create( clMax, FileOut);
Zip.CopyFrom(FileIni, FileIni.Size);
//Zip.CopyFrom(FileIni2, FileIni2.Size);
Zip.Free;
FileOut.Free;
FileIni.Free;
end;
Bom, agora como fazer para esta jossa descompactar os arquivos, separadamente,tipo retornar arquivo1, arquivo2?
Valew
procedure TForm1.Button1Click(Sender: TObject);
var
FileIni,FileIni2, FileOut: TFileStream;
Zip: TCompressionStream;
begin
FileIni := TFileStream.Create(´C:\Delivery\arquivo1´, fmOpenRead and fmShareExclusive);
FileIni2 := TFileStream.Create(´C:\Delivery\arquivo2, fmOpenRead and fmShareExclusive);
FileOut:=TFileStream.Create(´C:\Delivery\ArqCompact.arq´, fmCreate or fmShareExclusive);
Zip:=TCompressionStream.Create( clMax, FileOut);
Zip.CopyFrom(FileIni, FileIni.Size);
//Zip.CopyFrom(FileIni2, FileIni2.Size);
Zip.Free;
FileOut.Free;
FileIni.Free;
end;
Bom, agora como fazer para esta jossa descompactar os arquivos, separadamente,tipo retornar arquivo1, arquivo2?
Valew
GOSTEI 0
Marcelo Saviski
22/03/2005
Tente ´marcar´ onde começa e onde termina um arquivo, um cabeçalho de arquivo, nesse formato (não compilavel)
O Código da compressão ficou assim:
Agora vc chama ele passando o Nome de um Arquivo Destino e um array de Arquivos Fontes.
Para descompactar,, usando o TDecompressionStream, vc 1º leria um Integer N que informaria o nº de Arquivos comprimidos, depois passaria um loop para descarregar cada um destes N Arquivos, então vc leria outro inteiro que informaria quantos caracteres tem o nome original do arquivo, Alocaria espaço em uma string S com o [color=green:17fc05ab47]SetLength(NomeOriginalArq, NumCaracteres)[/color:17fc05ab47] e leria X bytes (X = nº caracteres) em NomeOriginalArq[1].
Depois leria outro Inteiro X que indicaria o tamanho do Arquivo (descomprimido), então descarregaria esses X Bytes no Arquivo S, por fim, leria mais 1 byte, e verificaria se ele é 0, para fins de verificação.
repita isso N vezes, até que todos os arquivos estejam extraidos.
para descomprimir vai ser sua tarefa fazer. :wink:
PS: eu nunca usei a ZLib antes, então talvez vc tenha que corrigir o código antes, por favor faça isso :)
PS2:Usei a Zlib que encontrei [url=http://www.koders.com/delphi/fidCCBD2263A7E1FD209D24E2924272520B32EF7B05.aspx?s=zlib]aqui[/url], espero que seja a mesma que vc usa
PS3: Não testei.
TMeuZip = packed record NumArquivos: Integer; Arquivos: array[1..NumArquivos] of packed record Len: Integer; //Tamanho FileInName FileInName: string[Len]; //Armazena o nome do Arquivo FileSize: Integer; //Tamanho em Bytes do Arquivo Arquivo: array[1..Filesize] of Byte; //Arquivo Armazenado Fim: Byte = 0; //indica um fim do arquivo, só para verificação end;
O Código da compressão ficou assim:
procedure Comprimir(FileOutName: TFileName; Files: array of TFileName); var FileInName: TFileName; FileIn, FileOut: TFileStream; Zip: TCompressionStream; NumArquivos, I, Len: Integer; begin FileOut := TFileStream.Create(FileOutName, fmCreate or fmShareExclusive); Zip := TCompressionStream.Create( clMax, FileOut); NumArquivos := Length(Files); Zip.Write(NumArquivos, SizeOf(Integer)); try for I := Low(Files) to High(Files) do begin FileIn := TFileStream.Create(Files[I], fmOpenRead and fmShareExclusive); try FileInName := ExtractFileName(Files[I]); Len := Length(FileInName); Zip.Write(Len, SizeOf(Integer)); Zip.Write(FileInName[1], Len); Zip.Write(FileIn.Size, SizeOf(Integer)); Zip.CopyFrom(FileIn, FileIn.Size); Zip.Write(0, 1); finally FileIn.Free; end; end; finally Zip.Free; FileOut.Free; end; end;
Agora vc chama ele passando o Nome de um Arquivo Destino e um array de Arquivos Fontes.
Comprimir(´C:\Delivery\ArqCompact.arq´, [´C:\Delivery\arquivo1´, ´C:\Delivery\arquivo2´]);
Para descompactar,, usando o TDecompressionStream, vc 1º leria um Integer N que informaria o nº de Arquivos comprimidos, depois passaria um loop para descarregar cada um destes N Arquivos, então vc leria outro inteiro que informaria quantos caracteres tem o nome original do arquivo, Alocaria espaço em uma string S com o [color=green:17fc05ab47]SetLength(NomeOriginalArq, NumCaracteres)[/color:17fc05ab47] e leria X bytes (X = nº caracteres) em NomeOriginalArq[1].
Depois leria outro Inteiro X que indicaria o tamanho do Arquivo (descomprimido), então descarregaria esses X Bytes no Arquivo S, por fim, leria mais 1 byte, e verificaria se ele é 0, para fins de verificação.
repita isso N vezes, até que todos os arquivos estejam extraidos.
para descomprimir vai ser sua tarefa fazer. :wink:
PS: eu nunca usei a ZLib antes, então talvez vc tenha que corrigir o código antes, por favor faça isso :)
PS2:Usei a Zlib que encontrei [url=http://www.koders.com/delphi/fidCCBD2263A7E1FD209D24E2924272520B32EF7B05.aspx?s=zlib]aqui[/url], espero que seja a mesma que vc usa
PS3: Não testei.
GOSTEI 0
Madrick
22/03/2005
Mano valew vou fazer um teste e dou retorno, T+ :?
GOSTEI 0
Madrick
22/03/2005
rpz a que eu entedi a logica em si, mas o lance que naum estou enchegando onde esta o erro as linhas de vermelho no codigo de compactação:
try
FileInName := ExtractFileName(Files[I]);
Len := Length(FileInName);
Zip.Write(Len, SizeOf(Integer));
Zip.Write(FileIn.Size,SizeOf(Integer)); [color=red:fc38836f4a]Erro : variable requered[/color:fc38836f4a]
Zip.CopyFrom(FileIn, FileIn.Size);
Zip.Write(FileInName[1], Len);
Zip.Write(0, 1); [color=red:fc38836f4a]Erro : variable requered[/color:fc38836f4a]
finally
FileIn.Free;
E quanto a descompactação naum saquei muito bem como pegar a informação do arquivo para saber quantos arquivos foram compactado, alguem tem mais uma ideia?
try
FileInName := ExtractFileName(Files[I]);
Len := Length(FileInName);
Zip.Write(Len, SizeOf(Integer));
Zip.Write(FileIn.Size,SizeOf(Integer)); [color=red:fc38836f4a]Erro : variable requered[/color:fc38836f4a]
Zip.CopyFrom(FileIn, FileIn.Size);
Zip.Write(FileInName[1], Len);
Zip.Write(0, 1); [color=red:fc38836f4a]Erro : variable requered[/color:fc38836f4a]
finally
FileIn.Free;
E quanto a descompactação naum saquei muito bem como pegar a informação do arquivo para saber quantos arquivos foram compactado, alguem tem mais uma ideia?
GOSTEI 0
Marcelo Saviski
22/03/2005
Ha...
então tem que declarar as variaveis, pensei que era só quando era pra ler os valores
poem lá aonde tá:
[color=green:957f6748e6]NumArquivos, I, Len: Integer; [/color:957f6748e6]
troca por:
[color=green:957f6748e6]NumArquivos, I, Len, Size: Integer;
Fim: Byte[/color:957f6748e6]
e aonde deu erro: mude para:
Para descomparctar, use como base o código que compacta, mas altere para ao invés de escrever os valores, carregue eles nas variaveis
então tem que declarar as variaveis, pensei que era só quando era pra ler os valores
poem lá aonde tá:
[color=green:957f6748e6]NumArquivos, I, Len: Integer; [/color:957f6748e6]
troca por:
[color=green:957f6748e6]NumArquivos, I, Len, Size: Integer;
Fim: Byte[/color:957f6748e6]
e aonde deu erro: mude para:
Size := FileIn.Size; Zip.Write(Size, SizeOf(Integer));
Fim := 0; Zip.Write(Fim, SizeOf(Byte));
Para descomparctar, use como base o código que compacta, mas altere para ao invés de escrever os valores, carregue eles nas variaveis
GOSTEI 0
Madrick
22/03/2005
Fiz uma função para tentar descomprimir o arquivo e usando o camando ´Read´ consegui capturar aqu quantidade de itens compactados, o tamanho do nome, o tamanho do arquivo mas na hora de pegar no nome do arquivo eu mando o read movendo o conteudo para uma string tipo:
zip.read(Nome, Len) onde len é o tamanho do nome visto acima;
ai ele retorna vazio inaccessible value;
Alguem tem alguma ideia do que pode ser isto;
Obs.: a compactação segue como no modelo pelo marcelo.
zip.read(Nome, Len) onde len é o tamanho do nome visto acima;
ai ele retorna vazio inaccessible value;
Alguem tem alguma ideia do que pode ser isto;
Obs.: a compactação segue como no modelo pelo marcelo.
GOSTEI 0
Madrick
22/03/2005
Galera esta parada tá me deixando de cabelo em pé, já passou ser uma questão de honra fazer um programa que funcione com o zlib.
Estou aberto a sugestões. :D
Estou aberto a sugestões. :D
GOSTEI 0
Madrick
22/03/2005
Galera sei que estou enchedo o saco com este post, mas não posso deixar esta parada passar em branco, até que me caia um raio na cabeça ou uma alma caridosa me ajude a encontrar uma solução.Descupas.. :lol:
GOSTEI 0
Madrick
22/03/2005
Galera ninguem tem mais nenhuma ideia?
GOSTEI 0
Nerdex
22/03/2005
Procure por este arquivo..:[color=green:940e07f001] 21894_a_single_unit_adding_zip_file_handling_to_delphi_1.1.zip[/color:940e07f001] no Code Central do Delphi e preste atenção nisso..:
[color=red:940e07f001]CommonFileHeader[/color:940e07f001]
Segue code preview...
Autores:
// Nick Naimo <nick@naimo.com> added support for folders on 6/29/2004 (see ´NJN´)
// Marcin Wojda <Marcin@sacer.com.pl> added exceptions and try finally blocks
p.s.: se não achar te mando por e-mail
[color=red:940e07f001]CommonFileHeader[/color:940e07f001]
Segue code preview...
procedure TZipFile.SaveToFile(const filename: string); var ZipFileStream: TFileStream; i: integer; begin ZipFileStream := TFileStream.Create(filename, fmCreate); try for i := 0 to High(Files) do with Files[i] do begin CentralDirectory[i].RelativeOffsetOfLocalHeader := ZipFileStream.Position; ZipFileStream.Write(LocalFileHeaderSignature, 4); if (LocalFileHeaderSignature = ($04034B50)) then begin ZipFileStream.Write(CommonFileHeader, SizeOf(CommonFileHeader)); ZipFileStream.Write(PChar(filename)^, CommonFileHeader.FilenameLength); ZipFileStream.Write(PChar(extrafield)^, CommonFileHeader.ExtraFieldLength); ZipFileStream.Write(PChar(CompressedData)^, CommonFileHeader.CompressedSize); end; end; EndOfCentralDirectory.OffsetOfStartOfCentralDirectory := ZipFileStream.Position; for i := 0 to High(CentralDirectory) do with CentralDirectory[i] do begin ZipFileStream.Write(CentralFileHeaderSignature, 4); ZipFileStream.Write(VersionMadeBy, 2); ZipFileStream.Write(CommonFileHeader, SizeOf(CommonFileHeader)); ZipFileStream.Write(FileCommentLength, 2); ZipFileStream.Write(DiskNumberStart, 2); ZipFileStream.Write(InternalFileAttributes, 2); ZipFileStream.Write(ExternalFileAttributes, 4); ZipFileStream.Write(RelativeOffsetOfLocalHeader, 4); ZipFileStream.Write(PChar(filename)^, length(filename)); ZipFileStream.Write(PChar(extrafield)^, length(extrafield)); ZipFileStream.Write(PChar(fileComment)^, length(fileComment)); end; with EndOfCentralDirectory do begin EndOfCentralDirSignature := $06054B50; NumberOfThisDisk := 0; NumberOfTheDiskWithTheStart := 0; TotalNumberOfEntriesOnThisDisk := High(Files) + 1; TotalNumberOfEntries := High(Files) + 1; SizeOfTheCentralDirectory := ZipFileStream.Position - OffsetOfStartOfCentralDirectory; ZipfileCommentLength := length(ZipFileComment); end; ZipFileStream.Write(EndOfCentralDirectory, SizeOf(EndOfCentralDirectory)); ZipFileStream.Write(PChar(ZipFileComment)^, length(ZipFileComment)); finally ZipFileStream.Free; end; end;
Autores:
// Nick Naimo <nick@naimo.com> added support for folders on 6/29/2004 (see ´NJN´)
// Marcin Wojda <Marcin@sacer.com.pl> added exceptions and try finally blocks
p.s.: se não achar te mando por e-mail
GOSTEI 0
Marcelo Saviski
22/03/2005
Veja se isso funciona:
Exemplo:
procedure Descomprimir(ZipFileName: TFileName; OutDir: string); resourcestring EDecompressionErrorMessage = ´Arquivo ¬s corrompido´; var FileOutName: string; FileIn, FileOut: TFileStream; Zip: TDecompressionStream; NumArquivos, I, Len, Size: Integer; Fim: Byte; begin FileIn := TFileStream.Create(ZipFileName, fmOpenRead and fmShareExclusive); Zip := TDecompressionStream.Create(FileIn); Zip.Read(NumArquivos, SizeOf(Integer)); try for I := 0 to NumArquivos - 1 do begin Zip.Read(Len, SizeOf(Integer)); SetLength(FileOutName, Len); Zip.Read(FileOutName[1], Len); Zip.Read(Size, SizeOf(Integer)); FileOut := TFileStream.Create(IncludeTrailingBackslash(OutDir) + FileOutName, fmCreate or fmShareExclusive); try FileOut.CopyFrom(Zip, Size); finally FileIn.Free; end; Zip.Read(Fim, SizeOf(Byte)); if Fim <> 0 then raise Exception.CreateFmt(EDecompressionErrorMessage, [ZipFileName]); end; finally Zip.Free; FileIn.Free; end; end;
Exemplo:
Descomprimir(´ArquivoComprimido´, ´DiretórioDestino´); Descomprimir(´C:\Arquivo.arq´, ´C:\ArquivoDescomprimido);
GOSTEI 0
Madrick
22/03/2005
Grande Marcelo Saviski, valew pela dica acredito que é isto mesmo, vou fazer um teste para conferir, sabado eu consegui fazer a descompactação e parece estar bem similar a sua, mas de toda forma, valew pela atenção. :D
GOSTEI 0
Marcelo Saviski
22/03/2005
vc pode enfeitar mais isso se quiser, tipo colocar mais detalhes sobre os arquivos, ou no incio uma espécie de ponteiro para o inicio dos arquivos na stream, assim cv poderia descompactar um arquivo especifico sem ter que descompactar todos.
Desse do BDN que o Nerdex falou, parece que tem bastante coisa lá, [url=http://cc.borland.com/search/results.aspx?keywords=zlib&prod=1&cat=4¬2c12¬2c14¬2c13¬2c2¬2c3¬2c16¬2c10¬2c15¬2c17¬2c11¬2c18¬2c9¬2c1]link[/url]
Desse do BDN que o Nerdex falou, parece que tem bastante coisa lá, [url=http://cc.borland.com/search/results.aspx?keywords=zlib&prod=1&cat=4¬2c12¬2c14¬2c13¬2c2¬2c3¬2c16¬2c10¬2c15¬2c17¬2c11¬2c18¬2c9¬2c1]link[/url]
GOSTEI 0
Madrick
22/03/2005
FileOut.CopyFrom(Zip, Size);
Esta forma esta acarretando um erro na seguinte linha:
Zip.Read(Fim, SizeOf(Byte));
Nesta linha que captura o dig. verificador está dando um erro de memoria muito louco, já fiz uns teste aqui mais naum identifiquei o porque, no meu codigo tinha ficado assim :
Zip.Read(Buf ,Size);
FileOut.Write(Buf, Size);
Zip.Read(Fim, SizeOf(Byte));
onde buf é um array do tipo Byte.
O problema que este tipo de implementação acarreta fica por conta do tamanho do array, que nã pode ser menor que o tamanho do arquivo a ser descompactado.
Valew. :wink:
Esta forma esta acarretando um erro na seguinte linha:
Zip.Read(Fim, SizeOf(Byte));
Nesta linha que captura o dig. verificador está dando um erro de memoria muito louco, já fiz uns teste aqui mais naum identifiquei o porque, no meu codigo tinha ficado assim :
Zip.Read(Buf ,Size);
FileOut.Write(Buf, Size);
Zip.Read(Fim, SizeOf(Byte));
onde buf é um array do tipo Byte.
O problema que este tipo de implementação acarreta fica por conta do tamanho do array, que nã pode ser menor que o tamanho do arquivo a ser descompactado.
Valew. :wink:
GOSTEI 0