Esse artigo faz parte da revista Clube Delphi edição 94. Clique aqui para ler todos os artigos desta edição
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; end; end; Este é provavelmente o método mais complicado da classe. Vamos precisar de um stream temporário que será, na verdade, o mesmo arquivo final, só que sem o arquivo deletado. Tivemos de fazer isso porque, ao deletarmos o arquivo no mesmo stream, depois não conseguimos reduzir o seu size para o tamanho novo (menor). Esse é o comportamento padrão de um TCompressionStream. O primeiro passo será então copiar para este arquivo novo todas as entradas até a de número Index (ReadEntry(True)). Depois ignoramos uma entrada (ReadEntry(False)) e copiamos o resto do arquivo (CopyEntireStream). Em seguida, substituímos o arquivo final atual pelo novo e repopulamos as entradas, pois estas foram modificadas. Pronto. Isso é tudo o que precisávamos para termos uma classe totalmente funcional com compactação para múltiplos arquivos. Agora precisamos construir uma interface com o usuário. ... 
![]()
Quer ler esse conteúdo completo?
Tenha acesso completo