Clique aqui para ler essa revista em PDF.
Expert
Streams
Implemente compactação, download em múltiplos pacotes e resources em suas aplicações com técnicas avançadas de Streams – Parte 2
Na edição anterior, iniciamos a criação de uma aplicação que faz uso intensivo de streams (Edição 93), que implementa compactação, download em múltiplos pacotes e resources. Desta vez, utilizaremos um stream temporário para escrever o arquivo que estamos lendo. Note que estamos utilizando GetDestStream e CleanDestStream para isso (vpeja última listagem da edição anterior). Portanto, poderemos estender essa classe futuramente para gerar a saída em um stream qualquer, não só em arquivos. Seguem suas implementações (não se esqueça da diretiva virtual neles. Veja na Listagem 1 a implementação das funções GetDestStream e CleanDestStream.
Listagem 1. Métodos GetDestStream e CleanDestStream
function TCompressor.GetDestStream(const DestFilePath:
string): TStream;
begin
Result := TFileStream.Create(DestFilePath,
fmCreate);
end;
procedure TCompressor.CleanDestStream(const
DestStream: TStream);
begin
DestStream.Free;
end;
Seu funcionamento também é básico: descartamos do arquivo Index – 1 entradas para posicionar o cursor do stream de leitura; depois lemos o tamanho do nome, o nome e o tamanho do arquivo, também para posicionar o cursor; e, finalmente, lemos o conteúdo do arquivo através de um CopyFrom do stream temporário.
Na Listagem 2 podemos ver a implementação de outro método importante, ReadEntry. Estamos apenas lendo uma entrada e descartando-a caso WriteResult seja false. Para finalizar, vejamos o método Delete descrito na Listagem 3.
Listagem 2. Método ReadEntry
procedure TCompressor.ReadEntry(WriteResult:
Boolean);
var
Buffer: TBuffer;
NameLength: Integer;
begin
FStreamRead.Read(Buffer, 4);
if WriteResult then
FStreamWrite.Write(Buffer, 4);
NameLength := BinToInt(CopyFromBuffer(Buffer, 4));
FStreamRead.Read(Buffer, NameLength);
if WriteResult then
FStreamWrite.Write(Buffer, NameLength);
FStreamRead.Read(Buffer, 8);
if WriteResult then
FStreamWrite.Write(Buffer, 8);
ReadFile(BinToInt64(CopyFromBuffer(Buffer, 8)), WriteResult);
end;
Listagem 3. Método Delete
procedure TCompressor.Delete(Index: Integer);
var
i: Integer;
ATempStream: TFileStream;
begin
RestartStream(fmOpenRead);
try
ATempStream := TFileStream.Create(FFilePath + '.tmp', fmCreate);
try
FStreamWrite := TCompressionStream.Create(clMax, ATempStream);
FStreamRead := TDecompressionStream.Create(FInternalStream);
for i := 0 to Index - 1 do
ReadEntry(True);
ReadEntry(False);
CopyEntireStream;
finally
CloseStreams;
ATempStream.Free;
end;
finally
CloseStreams;
end;
DeleteFile(FFilePath);
RenameFile(FFilePath + '.tmp', FFilePath);
RestartStream(fmOpenRead);
FStreamRead := TDecompressionStream.Create(FInternalStream);
try
PopulateEntries;
finally
CloseStreams;
" [...] continue lendo...