2

Why does this code not work?

I am writing an application that has ability to save and load its own files and need to know how to stream objects to a file using FileStream.

procedure TForm1.btnSaveClick(Sender: TObject); var fs: TFileStream; begin fs := TFileStream.Create('c:\temp\a.my', fmCreate); try fs.WriteBuffer(Image1.Picture.Graphic, SizeOf(TGraphic)); finally fs.Free; end; ShowMessage('ok'); Image1.Picture.Graphic := nil; end; procedure TForm1.btnLoadClick(Sender: TObject); var fs: TFileStream; g: TGraphic; begin fs := TFileStream.Create('c:\temp\a.my', fmOpenRead); try fs.ReadBuffer(g, SizeOf(TGraphic)); Image1.Picture.Graphic := g; finally fs.Free; end; ShowMessage('ok'); end; 

EDIT 1: Found the way to do it, but need some more help:

procedure TForm1.btnSaveClick(Sender: TObject); var fs: TFileStream; s: TMemoryStream; buf: TBytes; begin fs := TFileStream.Create('c:\temp\a.my', fmCreate); s := TMemoryStream.Create; try Image1.Picture.Graphic.SaveToStream(s); SetLength(buf, s.Size); s.Position := 0; s.ReadBuffer(buf[0], s.Size); //fs.WriteBuffer(, SizeOf(Integer)); <-here how do I save an integer which represents the size of the buffer? (so that when reading back i read this first.) fs.WriteBuffer(buf[0], s.Size); finally s.Free; fs.Free; end; ShowMessage('ok'); Image1.Picture.Graphic := nil; end; 
1

1 Answer 1

4

What you have done there is stream the reference, i.e. a pointer. What you need to stream is the contents. You can that with SaveToFile and LoadFromFile.

Regarding your update, assign s.Size to a local variable of type Integer and then use WriteBuffer to save it. In reverse, use ReadBuffer to read into a local variable.

If I were you I would write direct to the file and avoid the memory streak. Use the Position property of TStream to seek around the file. So write 0 for then length, write the graphic, seek back to the beginning and write the true length accounting for the 4 bytes of the length.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for responding. I have other objects in addition to the TGraphic so I have to use TFileStream's WriteBuffer and ReadBuffer to save and load files. I am going to edit my post to show my current code, in which i have a related question.
It's generally best to ask one question at a time. I already answered this one.
Need to know how to: "how do I save an integer which represents the size of the buffer?" in EDIT 1
@Steve See this post, it should give you an idea how to save / load data to/from stream.
@ain: Thanks. I see that you can just write an Integer using WriteBuffer. I was previously confused thinking that buffer has to be a memory (bytes) or string type.