Você está na página 1de 6

Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.

aspx

Manipulando Streams no Delphi 2010



Entre os vrios recursos que existem desde verses mais antigas do Delphi e ainda assim so pouco explorados
pelos desenvolvedores especializados na ferramenta, sem dvida um dos mais destacados so os Streams. Streams so
objetos que remetem ao incio dos tempos da programao, quando a manipulao de dados era feita byte a byte. Com o
surgimento de novas tecnologias, a utilizao dos Streams ficou restrita a situaes em que os mesmos so imprescindveis.
No Delphi existe uma classe base TStream e dela descendem as demais classes de manipulao de Streams:
TMemoryStream, TFileStream, TBlobStream. Essas trs classes que citei so as mais importantes na manipulao de Streams
em Delphi. Apesar de possurem diferenas entre si, a forma de trabalhar com cada uma das trs classes bem semelhante.
Nesse artigo estarei abordando de forma prtica o uso dos Streams utilizando a verso 2010 do Delphi. Porm os
exemplos funcionam em verses anteriores do Delphi com pouca ou nenhuma modificao.
Mos a obra!

FileStream
Como o prprio 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 utilizao da mesma
para outros tipos de arquivos perfeitamente possvel.
Inicie uma nova aplicao 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 exibio do mesmo.
Quando criamos um objeto FileStream no construtor do mesmo temos de informar alm do caminho do arquivo o
modo de abertura desse arquivo. FileStream nos possibilita quatro formas de abertura que so:
Fmcreate- Caso o arquivo no exista, ser criado. Caso exista, ser zerado e a escrita no mesmo ir sobrescrever
seu contedo 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 boto Carregar.
Segue o cdigo:

procedure TForm1.btncarregarClick(Sender: TObject);


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

1 de 6 27/03/17 1:10 PM
Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.aspx

edtcaminho.Text:=sFilename;
end;


Com o caminho do arquivo devidamente selecionado, iremos realizar a carga do mesmo para o FileStream e exibir o
contedo do mesmo no objeto memo que inserimos na aplicao.
Segue o cdigo:

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 alteraes e teste o aplicativo. Se tudo correu bem, o resultado ser semelhante ao mostrado na figura 2:

Figura 2

Stream com imagens
Embora no seja o mais recomendado, todos os servidores de banco de dados utilizados com o Delphi aceitam o
armazenamento de dados na forma binria atravs 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 vdeos, textos entre outros dados de
forma binria.
Para se trabalhar com campos Blob nos componentes DataSet existentes no Delphi, podemos lanar mo de mais
duas classes: TBlobStream, para os componentes BDE, e TMemorystream ou a prpria classe TStream para demais tipos de
DataSets. Com essas classes podero ser feitos o envio e recuperao de dados a partir de campos Blob. Lembrando que
para o Stream independe se o campo Blob contm um texto, uma imagem ou outra forma de dado. Sua funo apenas
servir de veculo para envio e recuperao dessas informaes.
Vamos a um exemplo prtico com Blob em combinao com outros dois objetos para carga de imagens. No
PageControl de nossa aplicao, adicione uma nova pgina e coloque como caption da mesma Blobstream. Em seguida
adicione a pgina 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 boto direito sobre o clientdataset e clique em
CreateDataSet.
Nesse exemplo estarei trabalhando com o clientdataset apenas em memria, 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 pgina conforme a figura 3.
Os outros dois objetos que estaremos utilizando so: TStream para a recuperao do contedo do Blob aps o
mesmo ter sido carregado. E TJpegImage para armazenar a imagem proveniente do campo Blob.

2 de 6 27/03/17 1:10 PM
Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.aspx

Figura 3
Lembrando que o componente OpenDialog no precisa ser criado novamente, ser utilizado o que j havamos criado
na primeira pgina.
Iremos selecionar o caminho de uma imagem para em seguida envi-lo para o Blobstream. Para a seleo do arquivo,
no evento OnClick do boto Selecionar faa:

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 extenso 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 tcnica do blobstream combinada com o Jpegimage.
Veja a codificao no evento OnClick do boto 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;

3 de 6 27/03/17 1:10 PM
Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.aspx


Repare que o objeto TJpegImage apenas serve de container provisrio para receber a imagem proveniente do campo
Blob.
Com essa tcnica podemos salvar e recuperar imagens em qualquer DataSet que oferea suporte aos campos Blob.
Salve as alteraes e teste o aplicativo. Um exemplo de resultado pode ser visto na figura 4:

Figura 4

Trabalhando com buers
Quando trabalhamos com Streams importante termos em mente que o contedo do Stream ir ocupar uma certa
quantidade de memria no computador. Em algumas situaes pode ser importante que tenhamos um controle mais preciso
desse espao e de como ele ser manipulado. Esse maior controle pode ser conseguido com a tcnica de buerizao, que
consiste em alocar previamente um espao de memria onde o buer ir trabalhar. Algo semelhante ao que feio com
ponteiros em linguagens como C++.
Antes de passarmos a prtica com buers, importante destacar duas propriedades importantes de um Stream, que
so: Size e Position.
Size retorna um inteiro com o tamanho ocupado pelo Stream, e Position tambm retorna um inteiro com a posio
atual do cursor de leitura do Stream. Assim como os datasets, Streams tambm possuem um cursor interno responsvel pela
leitura dos dados.
Vamos a prtica. Adicione uma nova pgina ao PageControl da aplicao 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 tcnica da buerizao e exibir seu contedo no Memo.
Seguem os cdigos:

Boto Selecionar Arquivo:

procedure TForm1.btnarqselecionarClick(Sender: TObject);

4 de 6 27/03/17 1:10 PM
Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.aspx

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


Boto 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 execuo na Figura 6:

Figura 6

Concluso
Streams so um excelente recurso disponibilizado pelo Delphi quando necessitamos utilizar tcnicas avanadas de
manipulao de arquivos em disco sendo carregados em memria.
Espero que tenham gostado e at a prxima!

5 de 6 27/03/17 1:10 PM
Artigos http://theclub.com.br/Restrito/Revistas/201004/mani1004.aspx

Sobre o Autor

Antonio Spitaleri Neto

Consultor Tcnico The Club

E-mail: suporte@theclub.com.br

6 de 6 27/03/17 1:10 PM