Mega Code Archive

 
Categories / Delphi / Examples
 

Tstream2

Subject: Re: [Delphi] Solution: Using TStream/TWri For those interested in storing components onto a stream, take a look at TWriter.WriteRootComponent and TWriter.WriteComponent. Then check out the TReader.Read... counterparts. Unfortunately, there appears to be no documentation showing HOW to use these methods properly. The docs keep mentioning the "root" component, but never clearly explain what it is or how you are suppose to use the root property to store your components. If you are interested in writing objects to the stream that are not components, I recommend doing something like the follow: type TMyObject = class(TObject) ... protected procedure SaveToStream(writer : TWriter); virtual; procedure LoadFromStream(writer : TWriter); virtual; ... end; procedure TMyObject.SaveToStream(writer : TWriter); begin with writer do begin WriteListBegin; {- write object state -} WriteListEnd; end; end; procedure TMyObject.LoadFromStream(reader : TReader); begin with reader do begin ReadListBegin; while not EndOfList do begin {- read object state -} end; ReadListEnd; end; end; Somewhere in the initialization section of the unit in which this object is declared, call RegisterObject('TMyObject'). (See RegisterObject() below.) In the main program, where you specify the file to read/write, you can do something like this: var RegisteredObjects : TStringList; procedure RegisterObject(cname : string; ctype : TClass); begin RegisteredObjects.AddObject(cname, ctype); end; procedure GetObject(cname : string) : TClass; var i : integer; begin i := RegisteredObjects.IndexOf(cname); if i > -1 then Result := TClass(RegisteredObjects.Objects[i]) else Result := nil; end; procedure SaveFile(const filename : string; objlist : TList); var stream : TFileStream; writer : TWriter; i : integer; begin stream := TFileStream.Create(filename, fmCreate or fmOpenWrite); try writer := TWriter.Create(stream, $ff); try with writer do begin WriteSignature; {marker to indicate a Delphi filer object file.} WriteListBegin; {outer list marker} for i := 0 to objlist.Count - 1 do begin WriteListBegin; {object marker} WriteString(TMyObject(objlist[i]).ClassName); TMyObject(objlist[i]).SaveToStream(writer); WriteListEnd; {object marker} end; WriteListEnd; {outer list marker} end; finally writer.Free; end; finally stream.Free; end; end; procedure OpenFile(const filename : string; objlist : TList); var stream : TFileStream; writer : TWriter; cname : string; {class name} ctype : TClass; {class type} obj : TObject; begin stream := TFileStream.Create(filename, fmOpenRead); try reader := TReader.Create(stream, $ff); try with reader do begin ReadSignature; {check Delphi filer object signature.} ReadListBegin; {outer list marker} while not EndOfList do begin ReadListBegin; {object marker} while not EndOfList do begin cname := ReadString; ctype := GetObjectClass(cname); obj := TObject(TObjectClass(ctype).Create; try obj.LoadFromStream(reader); except obj.Free; raise; end; objlist.Add(obj); end; ReadListEnd; {object marker} end; ReadListEnd; {outer list marker} end; finally reader.Free; end; finally stream.Free; end; end; Well, I don't know how far this will get you. I haven't tested ANY of this code, so who knows if it could ever possibly work. The most doubtful part is the whole dynamic instantiation taking place in LoadFromStream(). Delphi provides a bunch of great functions for registering TPersistent descendants and getting their class types from their class names, etc.: RegisterClass(), FindFieldClass(), FindClass(), GetClass(), etc. (They use it for loading components off of streams....no surprise there.) However, if your objects are not TPersistent descendants (and there's no reason they should be), then you're basically out of luck (read: "you get to write your own RegisteredClass()"). So, give this a try if you're feeling daring. Just don't come running after me with a shotgun complaining about little voices in your heads if you do. I suspect the above code will need a lot of polish before it does what is expected of it... Nonetheless, I hope you find it interesting, if nothing else. --Mark Johnson