Você está na página 1de 1

Manipulando Streams no Delphi 2010

 
Entre os vários recursos que existem desde versões mais antigas do Delphi e ainda assim são pouco explorados pelos
desenvolvedores especializados na ferramenta, sem dúvida um dos mais destacados são os Streams. Streams são objetos que
remetem ao início dos tempos da programação, quando a manipulação de dados era feita byte a byte. Com o surgimento de
novas tecnologias, a utilização dos Streams ficou restrita a situações em que os mesmos são imprescindíveis.
No Delphi existe uma classe base TStream e dela descendem as demais classes de manipulação de Streams:
TMemoryStream, TFileStream, TBlobStream. Essas três classes que citei são as mais importantes na manipulação de Streams em
Delphi. Apesar de possuírem diferenças entre si, a forma de trabalhar com cada uma das três classes é bem semelhante.
Nesse artigo estarei abordando de forma prática o uso dos Streams utilizando a versão 2010 do Delphi. Porém os
exemplos funcionam em versões anteriores do Delphi com pouca ou nenhuma modificação.
Mãos a obra!
 
FileStream
Como o próprio nome já sugere, a classe TFileStream, descendente de TStream, manipula arquivos em disco na forma
de Streams. Em geral utilizamos essa forma de Stream para manipular arquivos de texto, mas a utilização da mesma para outros
tipos de arquivos é perfeitamente possível.
Inicie uma nova aplicação no Delphi e monte o layout da mesma conforme a figura 1:
 

Figura 1
 
O que faremos a seguir é carregar um arquivo texto para um objeto FileStream e em seguida carregar esse Stream no
objeto Memo para exibição do mesmo.
Quando criamos um objeto FileStream no construtor do mesmo temos de informar além do caminho do arquivo o
modo de abertura desse arquivo. FileStream nos possibilita quatro formas de abertura que são:
Fmcreate- Caso o arquivo não exista, será criado. Caso exista, será zerado e a escrita no mesmo irá sobrescrever seu
conteúdo atual;
Fmopenread- Abre o arquivo apenas para leitura;
Fmopenwrite-  Abre o arquivo apenas para escrita;
Fmopenreadwrite- Abre o arquivo para leitura e escrita.
 
O primeiro passo será a busca do arquivo com o OpenDialog, que será feita no evento OnClick do botão “Carregar”.
Segue o código:
 

procedure TForm1.btncarregarClick(Sender: TObject);


var
sFilename:string;
begin
if(OpenDialog1.Execute)then
sFilename:=OpenDialog1.FileName;
edtcaminho.Text:=sFilename;
end;

 
Com o caminho do arquivo devidamente selecionado, iremos realizar a carga do mesmo para o FileStream e exibir o
conteúdo do mesmo no objeto memo que inserimos na aplicação.
Segue o código:
 

procedure TForm1.btnexibirClick(Sender: TObject);


var
sFilename:string;
oFileStream:TFileStream;
begin
try
sFilename:=edtcaminho.Text;
oFileStream:=TFileStream.Create(sFilename,fmOpenRead);
memstream.Lines.LoadFromStream(oFileStream);
finally
FreeAndNil(oFileStream);
end;
end;

 
Salve as alterações e teste o aplicativo. Se tudo correu bem, o resultado será semelhante ao mostrado na figura 2:

Figura 2
 
Stream com imagens
Embora não seja o mais recomendado, todos os servidores de banco de dados utilizados com o Delphi aceitam o
armazenamento de dados na forma binária através de campos Blob. Esse tipo de campo em geral é utilizado para o
armazenamento de imagens no banco de dados, mas pode ser utilizado para armazenar vídeos, textos entre outros dados de
forma binária.
Para se trabalhar com campos Blob nos componentes DataSet existentes no Delphi, podemos lançar mão de mais duas
classes: TBlobStream, para os componentes BDE, e TMemorystream ou a própria classe TStream para demais tipos de DataSets.
Com essas classes poderão ser feitos o envio e recuperação de dados a partir de campos Blob. Lembrando que para o Stream
independe se o campo Blob contém um texto, uma imagem ou outra forma de dado. Sua função é apenas servir de veículo para
envio e recuperação dessas informações.
Vamos a um exemplo prático com Blob em combinação com outros dois objetos para carga de imagens. No
PageControl de nossa aplicação, adicione uma nova página e coloque como caption da mesma “Blobstream”. Em seguida
adicione a página um componente Clientdataset, alterando seu nome para CdsBlob. Abra o FieldsEditor do clientdataset e
adicione campo Blob com o nome de IMAGEM. Isso feito clique com o botão direito sobre o clientdataset e clique em
CreateDataSet.
Nesse exemplo estarei trabalhando com o clientdataset apenas em memória, mas ele poderia estar ligado a uma fonte
de dados sem problemas.
Com o clientdataset devidamente criado e configurado, monte o restante do layout da página conforme a figura 3.
Os outros dois objetos que estaremos utilizando são: TStream para a recuperação do conteúdo do Blob após o mesmo
ter sido carregado. E TJpegImage para armazenar a imagem proveniente do campo Blob.
 

Figura 3
Lembrando que o componente OpenDialog não precisa ser criado novamente, será utilizado o que já havíamos criado
na primeira página.
Iremos selecionar o caminho de uma imagem para em seguida enviá-lo para o Blobstream. Para a seleção do arquivo,
no evento OnClick do botão “Selecionar” faça:
 

procedure TForm1.SelecionarClick(Sender: TObject);


begin
OpenDialog1.Filter:=EmptyStr;
OpenDialog1.Filter:='Image Files|*.jpg';
if(OpenDialog1.Execute)then
edtcaminhoimg.Text:=OpenDialog1.FileName;
end;

 
Alteramos o filtro do OpenDialog para que apenas aceite imagens com a extensão jpeg e em seguida salvamos o
caminho do arquivo de imagem na Edit edtcaminho.
Como estamos trabalhando com imagens em formato Jpeg devemos adicionar na uses da unit a biblioteca Jpeg.
Iremos agora salvar essa imagem já selecionada em um FileStream, salvá-la no campo blob e depois recuperá-la com a
técnica do blobstream combinada com o Jpegimage.
Veja a codificação no evento OnClick do botão “Salvar”:
 

procedure TForm1.SalvarClick(Sender: TObject);


var
sFilename:string;
oFilestream:TFileStream;
oMemorystream:TStream;
oImage:TJPEGImage;
begin
try
sFilename:=edtcaminhoimg.Text;
oFilestream:=TFileStream.Create(sFilename,fmOpenRead);
oMemorystream:=TMemoryStream.Create;
oImage:=TJPEGImage.Create;
cdsblob.Open;
cdsblob.Append;
cdsblobIMAGEM.LoadFromStream(oFilestream);
cdsblob.Post;
oMemorystream:=cdsblob.CreateBlobStream(cdsblobIMAGEM,bmRead);
oImage.LoadFromStream(oMemorystream);
Image1.Picture.Assign(oImage);
finally
FreeAndNil(oFilestream);
FreeAndNil(oMemorystream);
FreeAndNil(oImage);
end;

 
Repare que o objeto TJpegImage apenas serve de container provisório para receber a imagem proveniente do campo
Blob.
Com essa técnica podemos salvar e recuperar imagens em qualquer DataSet que ofereça suporte aos campos Blob.
Salve as alterações e teste o aplicativo. Um exemplo de resultado pode ser visto na figura 4:
 

Figura 4
 
Trabalhando com buffers
Quando trabalhamos com Streams é importante termos em mente que o conteúdo do Stream irá ocupar uma certa
quantidade de memória no computador. Em algumas situações pode ser importante que tenhamos um controle mais preciso
desse espaço e de como ele será manipulado. Esse maior controle pode ser conseguido com a técnica de “bufferização”, que
consiste em alocar previamente um espaço de memória onde o buffer irá trabalhar. Algo semelhante ao que é feio com
ponteiros em linguagens como C++.
Antes de passarmos a prática com buffers, é importante destacar duas propriedades importantes de um Stream, que
são: Size e Position.
Size retorna um inteiro com o tamanho ocupado pelo Stream, e Position também retorna um inteiro com a posição
atual do cursor de leitura do Stream. Assim como os datasets, Streams também possuem um cursor interno responsável pela
leitura dos dados.
Vamos a prática. Adicione uma nova página ao PageControl da aplicação e monte seu layout conforme a figura 5:
 

Figura 5
 
Nesse exemplo iremos selecionar um arquivo texto, carregá-lo para um FileStream, em seguida copiá-lo para outro
FileStream com a técnica da bufferização e exibir seu conteúdo no Memo.
Seguem os códigos:

Botão “Selecionar Arquivo”:

procedure TForm1.btnarqselecionarClick(Sender: TObject);


begin
if(OpenDialog1.Execute)then
edtcaminhoarq.Text:=OpenDialog1.FileName;
end;

 
Botão “Copiar”:

procedure TForm1.btncopiarClick(Sender: TObject);


var
oStreamin,
oStreamout:TFileStream;
aBufferstream:array[0..1023]of Byte;
iByteRead:integer;
sFilename:string;
begin
try
ProgressBar1.Position:=0;
sFilename:=edtcaminhoarq.Text;
oStreamin:=TFileStream.Create(sFilename,fmOpenRead);
oStreamout:=TFileStream.Create('temp.txt',fmCreate);
repeat
iByteRead:=oStreamin.Read(aBufferstream,1024);
oStreamout.Write(abufferstream,iByteRead);
ProgressBar1.StepBy(1);
until(iByteRead=0);
finally
ProgressBar1.Position:=100;
FreeAndNil(oStreamin);
FreeAndNil(oStreamout);
Memo1.Lines.LoadFromFile('temp.txt');
end;
end;

 
Veja o aplicativo em execução na Figura 6:
 

Figura 6
Conclusão
Streams são um excelente recurso disponibilizado pelo Delphi quando necessitamos utilizar técnicas avançadas de
manipulação de arquivos em disco sendo carregados em memória.
Espero que tenham gostado e até a próxima!

Sobre o Autor
Antonio Spitaleri Neto

Consultor Técnico The Club

E-mail: suporte@theclub.com.br

Você também pode gostar