Esse artigo faz parte da revista Clube Delphi Edição 93. Clique aqui para ler todos os artigos desta edição
image
Clique aqui para ler esse artigo em PDF. imagem_pdf.jpg
  • Avançado
  • Streams
  • Implemente compactação, download em múltiplos pacotes e resources em suas aplicações com técnicas avançadas de Streams – Parte 1

Aí está o grande pesadelo de grande parte dos programadores Delphi. Muitos, quando ouvem falar em streams, desistem do código na hora! Mas, por que será que causa tanto medo? Talvez, isso se deva ao fato de estarmos trabalhando diretamente com bits e bytes. E isso nos remete aos “malucos escovadores de bits” de décadas atrás. Hoje, temos orientação a objetos, a adoção do garbage collector pelas mais diversas linguagens, dentre outros conceitos e técnicas que deixam nossa vida muito mais fácil. Por isso, desacostumamos com o fato de que, por trás de tudo, ainda temos os mesmos ponteiros, bits e bytes.

Neste artigo, veremos que streams são, na verdade, muito simples e podem ser utilizados por qualquer programador. Todos os que já trabalharam com arrays, listas (TStringList, TObjectList), datasets, ou qualquer tipo de coleção, não devem encontrar dificuldade para utilizar todos os recursos da classe TStream.

Com exemplos práticos e objetivos, abordaremos também dois assuntos extremamente relacionados: Compression e Resources. Veremos que não é necessário fazer o download nenhuma biblioteca para trabalhar com arquivos compactados, uma vez que o Delphi já implementa a sua. Construiremos, passo a passo, uma aplicação para compactação de múltiplos arquivos.

Quanto aos Resources, além do exemplo clássico de embutir uma DLL dentro de seu executável, aprenderemos também, a fundo, a alterar os recursos de outras aplicações, bem como a modificar suas resourcestrings. Enfim, tudo o que há de mais avançado no assunto.

Streams

Imagine um dataset bidirecional, como o TClientDataSet ou o TTable. Porém, em vez de armazenar registros e campos de um banco de dados, armazenaremos bytes, um após o outro, de um arquivo que está no disco. Podemos pegar seu tamanho final, temos a possibilidade de navegar entre os bytes, etc., como se fossem registros.

Streams podem ser entendidos como uma seqüência de bytes na memória. Esses bytes podem ser tanto de um programa que foi carregado, como de uma string qualquer, um arquivo de recurso, ou como uma seqüência de bytes qualquer que desejamos representar. Analisemos código presente na Listagem 1.


procedure TForm1.Button1Click(Sender: TObject);
var
  FileStreamIn: TFileStream;
  FileStreamOut: TFileStream;
begin
  FileStreamIn := TFileStream.Create('caminho para arquivo de entrada',
    fmOpenRead);
  FileStreamOut := TFileStream.Create('caminho para arquivo de saída',
    fmCreate);
  try
    FileStreamOut.CopyFrom(FileStreamIn, FileStreamIn.Size)
  finally
    FileStreamIn.Free;
    FileStreamOut.Free;
  end;
end;
Listagem 1. Trecho de código utilizando Streams

A classe TFileStream herda de TStream e serve para representarmos arquivos do disco na memória. Seu uso é muito simples. No seu construtor, devemos passar: o caminho para o arquivo a ser representado e o modo de abertura desse arquivo. (ver nota “Modos de Abertura de Arquivos”)

Nota: Modos de Abertura de Arquivos
  • fmCreate: Caso o arquivo não exista, será criado. Caso exista, será zerado para que se comece um novo.
  • fmOpenRead: Apenas para leitura.
  • fmOpenWrite: Apenas para escrita.
  • fmOpenReadWrite: Leitura e escrita.

Vale lembrar que o arquivo ficará bloqueado para outros streams (e outros programas) até que o stream seja fechado. Como não existe um método Close, a única maneira de fazermos isso é chamando seu destrutor (ou Free). Portanto, é muito importante fechar o stream para que o arquivo seja liberado.

No exemplo citado, estamos criando dois streams do tipo TFileStream e chamando o método CopyFrom do que está criando o arquivo. Portanto, estamos simplesmente criando uma cópia do arquivo. Além disso, notamos que esse método necessita da quantidade de bytes que gostaríamos de copiar. No caso, utilizamos o arquivo inteiro (Size). Vejamos agora outro tipo de stream, também descendente de TStream, o TStringStream. Vamos modificar a entrada de dados para uma string na memória. (Listagem 2)


procedure TForm1.Button1Click(Sender: TObject);
var
  StringStreamIn: TStringStream;
  FileStreamOut: TFileStream;
begin
  StringStreamIn:= TStringStream.Create('string no stream');
  FileStreamOut:= TFileStream.Create('caminho para arquivo de saída',
    fmCreate);

  try
    FileStreamOut.CopyFrom(StringStreamIn, StringStreamIn.Size);
  finally
    StringStreamIn.Free;
    FileStreamOut.Free;
  end;
end;
Listagem 2. Trecho de código utilizando Streams

A classe TStringStream se difere da anterior apenas pela fonte de dados, que agora é uma string. Esta classe possui uma propriedade especial DataString, pela qual é possível sabermos qual a ...

Quer ler esse conteúdo completo? Tenha acesso completo