1

please , suppose i have this Binary Tree structure :

Type
    TPMyTree = ^TMyTree;
    TMyTree = Record
        ID:Integer;
        FullName:String[50];//<-------- fixed
        addrs:String[50] // <----------- fixed
        LeftT:TPMyTree;
        RightT:TPMyTree;
    end;

How could i save and load it from a Stream ?

Alexis
  • 141
  • 1
  • 5
  • 1
    http://stackoverflow.com/questions/3820996/delphi-2010-how-to-save-a-whole-record-to-a-file – Ville Krumlinde Jan 11 '12 at 13:16
  • I provided an answer to the question itself, but have to ask: Why do you need to do this? If you need this for more then an exercise I suggest replacing the variable-length string with something fixed (like the `string[number]`) and structuring your tree so Left and Right sub-nodes are not actual pointers but indexes into a big buffer. That way you'll be able to read and write the whole index in one go, not one node at a time. And if this gets to large numbers of nodes, make sure you look into tree data structures designed to work with the disk, like the B-Tree. – Cosmin Prund Jan 11 '12 at 13:33
  • Do you want to save to an XML or text format, or to a binary format? From you using String[50] I get the idea you want to use binary formats. I recommend you do not use binary formats at all, and save to a text format instead. I realize you updated your question because the answer you were given says "variable length data is not easy to handle in binary formats". I would have said, JUST DON'T DO BINARY FORMATS. Bad idea. – Warren P Jan 11 '12 at 23:44

1 Answers1

1

When working with streams, the most complex issue is dealing with variable-length data. In your case that's the FullName and the addrs, because those fields are of type String. The easiest solution is to use Delphi's stream reader and writer helper classes, TReader and TWriter, because they provide easy means of working with string. Other thant that the most obvious solution is to write the tree to the stream recursively, one node at a time.

Warning, code written in browser window:

// This will save one node to the stream, using the TWriter helper. Takes
// care of potential NIL's.
procedure SaveBinaryTreeToStreamWriter(RootNode: TPMyTree; W: TWriter);
begin
  if Assigned(RootNode) then
    begin
      W.WriteBoolean(True);
      W.WriteInteger(RootNode^.ID);
      W.WriteString(RootNode^.FullName);
      W.WriteString(RootNode^.addres);
      SaveBinaryTreeToStreamWriter(RootNode^.LeftT, W);
      SaveBinaryTreeToStreamWriter(RootNode^.RightT, W);
    end
  else
    W.WriteBoolean(False);
end;

// This will read one NODE from the stream, using the TReader helper.
// Uses the boolean "nil" marker saved by the writing routine to also
// return "nil" if needed.
function ReadBinaryTreeNodeFromReader(R: TReader):TPMyTree;
begin
  if R.ReadBoolean then
    begin
      Result := AllocMem(SizeOf(TMyTree));
      Result^.ID := R.ReadInteger;
      Result^.FullName := R.ReadString;
      Result^.addres := R.ReadString;
      Result^.LeftT := ReadBinaryTreeNodeFromReader(R);
      Result^.RightT := ReadBinaryTreeNodeFromReader(R);
    end
  else
    Result := nil;
end;

// This simply creates the TWriter and then starts the recursive process of
// writing the tree to stream.
procedure SaveBinaryTreeToStream(RootNode: TPMyTree; Stream: TStream);
var W:TWriter;
begin
  W := TWriter.Create(Stream, 128);
  try
    SaveBinaryTreeToStreamWriter(RootNode, W);
  finally W.Free;
  end;
end;    

// This simply creates the TReader and then starts the recursive process of
// reading the tree one node at a time:
function ReadFromStream(Stream:TStream):TPMyTree;
var R: TReader;
begin
  R := TReader.Create(Stream, 128);
  try
    Result := ReadBinaryTreeNodeFromReader(R);
  finally R.Free;
  end;    
end;
Cosmin Prund
  • 25,498
  • 2
  • 60
  • 104
  • Now FullName and addrs have a fixed size – Alexis Jan 11 '12 at 15:45
  • Still a bad idea. You do realize that String[50] means you are now storing Ansi Characters, up to 50 of them, and that unicode characters you store to that record (in unicode delphi versions) will not be able to be stored in your String[50] field. (Fixed length field with character type AnsiChar). – Warren P Jan 11 '12 at 23:46