Board index » delphi » Using streams to read/write binary file

Using streams to read/write binary file

Hello,

Being an old "C" programmer, I am used to the concept of
reading/writing different structures as binary bytes to a binary file
in order to save an applications data.

I need to save many different interrelated data objects (the data
objects I've stored in TLists) to a binary file in Delphi. I think the
way to go is with TFileStreams (Create, WriteBuf, ...), but then I see
TFiler, TReader, TWriter and I get all confused. Can someone briefly
outline the functions and methods they use to accomplish this.

Many thanks,
Barry.

 

Re:Using streams to read/write binary file


        If you're just writing and reading data to/from files then all you need
is TFileStream - those other Txxx things are for streaming components (I think).
        You simply Create a stream, Write your data and Free the stream. Like

var s:TFileStream;j:longint;
begin
S:=TFileStream.Create('c:\deldemos\afile.txt',fmCreate);
j:=2;
S.Write(j,SizeOf(longint));
j:=3;
S.Write(j,SizeOf(longint));
S.Free;
end;

        Similarly for more interesting data types.
        WriteBuf does the same thing except it raises an exception if the
requested number of bytes was not written.

        OTOH you say you want to save TLists. A list is an object, not just data -
if you try the above on a TList you write only 4 bytes to the file (that being the
value of the pointer which the list "is"). Probably the best thing might be to
finagle an array out of the data and write the array instead of writing the actual
TList. If you really want to write the list I gather you can use a TWriter to do
that; it has a bunch of extra methods (as I gather you noticed).

--
David Ullrich
Don't you guys find it tedious typing the same thing
after your signature each time you post something?
I know I do, but when in Rome...

Re:Using streams to read/write binary file


Quote
David Ullrich <ullr...@math.okstate.edu> wrote:
>    OTOH you say you want to save TLists. A list is an object, not just data -
>if you try the above on a TList you write only 4 bytes to the file (that being the
>value of the pointer which the list "is"). Probably the best thing might be to
>finagle an array out of the data and write the array instead of writing the actual
>TList.

Thanks,
You're right I do want to save the objects pointed to in the TList. I
have run into the 4 byte pointer size as the sizeof(Object). There is
something like InstanceSize() which returns the actual object size.

Will something like:
     S.Write(obj^ ,InstanceSize(TObjectName));
do anything.

Thanks,
Barry.

Re:Using streams to read/write binary file


Quote
>Will something like:
>     S.Write(obj^ ,InstanceSize(TObjectName));
>do anything.

        Well, no. You could write the list's Items (or rather the Item[j]^'s)
to a TFileStream or (depending on what sort of objects the items are) you could
use the methods in TWriter and TReader. The following gives me a 12-byte file,
presumably containing useless information about the list object itself:

var FS:TFileStream; L:TList; j:longint;
begin
     L:=TList.Create;
     for j:=1 to 10 do L.Add(@j);
  FS:=TFileStream.Create('c:\hmm.hmm',fmCreate);
  FS.Write(L,L.InstanceSize);
end;

        OTOH if I do

var FS:TFileStream;L:TList; j:longint;
begin
     L:=TList.Create;
     for j:=0 to 10 do L.Add(@j);
  FS:=TFileStream.Create('c:\hmm.hmm',fmCreate);
  for j:=0 to 10 do FS.Write(L.Items[j]^,4);
  FS.Free;
  L.Free;
end;

I get a file containing 11 longints as I'd hope.

--
David Ullrich
Don't you guys find it tedious typing the same thing
after your signature each time you post something?
I know I do, but when in Rome...

Re:Using streams to read/write binary file


Quote
bfsch...@cat.syr.edu (Barry) wrote:
>You're right I do want to save the objects pointed to in the TList. I
>have run into the 4 byte pointer size as the sizeof(Object). There is
>something like InstanceSize() which returns the actual object size.

>Will something like:
>     S.Write(obj^ ,InstanceSize(TObjectName));
>do anything.

It'll write some bytes, but they won't be readable.  Objects generally
contain pointers to structures in memory (like the virtual method
table, other objects, etc.) and you can't just read those in, they
need to be reconstructed.  I think you need to use the TWriter and
TReader objects; unfortunately, Borland didn't document them properly.

Duncan Murdoch

Re:Using streams to read/write binary file


Quote
David Ullrich <ullr...@math.okstate.edu> wrote:
>    If you're just writing and reading data to/from files then all you need
>is TFileStream - those other Txxx things are for streaming components (I think).
>    You simply Create a stream, Write your data and Free the stream. Like

>var s:TFileStream;j:longint;
>begin
>S:=TFileStream.Create('c:\deldemos\afile.txt',fmCreate);
>j:=2;
>S.Write(j,SizeOf(longint));
>j:=3;
>S.Write(j,SizeOf(longint));
>S.Free;
>end;

>    Similarly for more interesting data types.
>    WriteBuf does the same thing except it raises an exception if the
>requested number of bytes was not written.

>    OTOH you say you want to save TLists. A list is an object, not just data -
>if you try the above on a TList you write only 4 bytes to the file (that being the
>value of the pointer which the list "is"). Probably the best thing might be to
>finagle an array out of the data and write the array instead of writing the actual
>TList. If you really want to write the list I gather you can use a TWriter to do
>that; it has a bunch of extra methods (as I gather you noticed).

>--
>David Ullrich
>Don't you guys find it tedious typing the same thing
>after your signature each time you post something?
>I know I do, but when in Rome...

You can use TWriter to store a class to a file, but it will not help much because you
cannot read it back! You have no information how to restore your classes.

To save an object to a file that is not a descendant of TPersistent get my object7
unit from http://sunsite.icm.edu.pl/~robert/delphi  in the freeware section. It does
what you want and a little more.

Best regards

Guy FInk (By kind permission of Alain Rassel)

Re:Using streams to read/write binary file


Quote
dmurd...@mast.queensu.ca (Duncan Murdoch) wrote:
>bfsch...@cat.syr.edu (Barry) wrote:

>>You're right I do want to save the objects pointed to in the TList. I
>>have run into the 4 byte pointer size as the sizeof(Object). There is
>>something like InstanceSize() which returns the actual object size.

>>Will something like:
>>     S.Write(obj^ ,InstanceSize(TObjectName));
>>do anything.

>It'll write some bytes, but they won't be readable.  Objects generally
>contain pointers to structures in memory (like the virtual method
>table, other objects, etc.) and you can't just read those in, they
>need to be reconstructed.  I think you need to use the TWriter and
>TReader objects; unfortunately, Borland didn't document them properly.

>Duncan Murdoch

Hi

No it is not possible to write an object to a file that is not a
descendant of TPersistent.. at least not with the units Borland
delivers.:(

There is much more to do than to know the objects size, infact it is
useless because it is an implicit property of the object. So if you want
to know how to do it get my objects7 unit from :

  http://www.sunsite.icm.edu.pl/~robert/delphi

in the freeware section. Source code is included, it reiplements the
objects unit from BP 7 under Delphi

Best regards

Guy Fink (By kind permission of Alain Rassel)

Other Threads