Streaming TOwnedCollection descendant from flat file

I have a TOwnedCollection descendant  that I am using (for my collection items). Can someone point me to some sample code for loading (streaming) my collection from a fla file.

Thanks, Tom.
boardtcAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CesarioCommented:
Hi tom,


Procedure TForm1.FormCreate(..);
Begin
  RegisterClass ( YourCollection );
 RegisterClass ( your CollectionItemClass );  // registerClass (TMyCollItem);
End;


To load the Collection
ReadComponentResFile(FileName: string,YourCollectio)

To save it ( the Collection should be created before calling this functiuon):
procedure WriteComponentResFile( FileNam,yourCollection);

best Regards

Cesario
0
boardtcAuthor Commented:
Thanks for the note. WriteComponentResFile looks for a TComponent descendant for "yourCollection", I want to pass a TownedCollection descendant. ANy ideas what I need to do? Cheers, tom.
0
EngwiCommented:
Tom

What does the class declaration look like for your decendant.

Reading the file should be quite easy, just use the data returned with the add function in your class to add items to the collection.

Regards
 Engwi
0
Amazon Web Services

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

CesarioCommented:
How to implement TCollection.SaveToStream

procedure ReadCollection(s: TStream; c: TCollection);
var
  Reader: TReader;
begin
  Reader := TReader.Create(s, 1024);
  try
    Reader.ReadValue;  {collection marker}
    Reader.ReadCollection(c);
  finally
    Reader.Free;
  end;
end;
 
 
procedure WriteCollection(s: TStream; c: TCollection);
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(s, 1024);
  try
    Writer.WriteCollection(c);
  finally
    Writer.Free;
  end;
end;


Now WriteCollection (your Collection  Var )
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
boardtcAuthor Commented:
Engwi,
  TMyCollection = class(TOwnedCollection)
....sure the add gives me the TMyCollectionItem but I am trying to figure out how to stream the date to a file.....

Cesario I added :

procedure WriteFile(const FileName: string; Collection : TCollection);
  var
    AFile : TFileStream;
begin
  AFile := TFileStream.Create(FileName,fmCreate or fmOpenWrite);
  try
    WriteCollection(AFile,Collection);
  finally
    AFile.Free;
  end;
end;

procedure ReadFile(const FileName: string; Collection : TCollection);
  var
    AFile : TFileStream;
begin
  AFile := TFileStream.Create(FileName,fmOpenRead);
  try
    ReadCollection(AFile,Collection);
  finally
    AFile.Free;
  end;
end;

This works great, thanks. Note it works with or without the (single) RegisterClass(TMyCollection).

The resultant file has binary stuff in it and is not very pretty. How can I get it to produce neat output in the file like Delphi does with the dfm?

Thanks a lot,

Tom.


0
StefaanCommented:
Ok, here is a little sample, it contains a form and two buttons, one for writing out the Collection and one for reading in the Collection.

As you will see there is a descendant of an OwnedCollection there TTests with its CollectionItems TTest, and both will be streamed to a file and read back in.  The trick was to use a Componet Wrapper just like Borland did in the VCL ( see GridColumns of a TdbGrid ).

Here it is :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btnButton1: TButton;
    btnButton2: TButton;
    procedure btnButton1Click(Sender: TObject);
    procedure btnButton2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TTest = class( TCollectionItem )
  private
    FTestInteger: Integer;
    FTestString: String;
  public
    procedure Assign( Source : TPersistent ); override;

  published
    property TestString  : String  read FTestString  write FTestString;
    property TestInteger : Integer read FTestInteger write FTestInteger;
  end;

  TTests = class( TOwnedCollection )
  private
    FMyName: String;
  public
    procedure Assign( Source : TPersistent ); override;

    procedure LoadFromFile(const Filename: string);
    procedure LoadFromStream(S: TStream);

    procedure SaveToFile(const Filename: string);
    procedure SaveToStream(S: TStream);
  published
    property MyName : String read FMyName write FMyName;
  end;

  TCollectionWrapper = class( TComponent )
  private
    FTests : TTests;
  published
    property Tests : TTests read FTests write FTests;
  end;

var
  Form1: TForm1;

implementation

{$IFDEF CODESITE}
uses
  csIntf;
{$ENDIF}

{$R *.dfm}

{ TMyOwnedCollection }

procedure TTests.Assign(Source: TPersistent);
begin
  if ( Source is TTests ) then
  begin
    MyName := TTests( Source ).MyName;
  end;

  inherited;
end;

procedure TTests.LoadFromFile(const Filename: string);
var
  S: TFileStream;
begin
  S := TFileStream.Create(Filename, fmOpenRead);
  try
    LoadFromStream(S);
  finally
    S.Free;
  end;
end;

procedure TTests.LoadFromStream(S: TStream);
var
  Wrapper: TCollectionWrapper;
begin
  Wrapper := TCollectionWrapper.Create(nil);
  try
    Wrapper.Tests := TTests.Create( Self, TTest );
    S.ReadComponent( Wrapper);
    Assign(Wrapper.Tests);
  finally
    Wrapper.Tests.Free;
    Wrapper.Free;
  end;
end;

procedure TTests.SaveToFile(const Filename: string);
var
  S: TStream;
begin
  S := TFileStream.Create(Filename, fmCreate);
  try
    SaveToStream(S);
  finally
    S.Free;
  end;
end;

procedure TTests.SaveToStream(S: TStream);
var
  Wrapper: TCollectionWrapper;
begin
  Wrapper := TCollectionWrapper.Create(nil);
  try
    Wrapper.Tests := Self;
    S.WriteComponent(Wrapper);
  finally
    Wrapper.Free;
  end;
end;

{ TMyOwnedCollectionWrapper }

procedure TForm1.btnButton1Click(Sender: TObject);
var
  aTests : TTests;
  aTest  : TTest;
  lcv    : Integer;
begin
  aTests := TTests.Create( Self, TTest );
  aTests.MyName := 'Test';
  for lcv := 0 to 9 do
  begin
    aTest := TTest( aTests.Add );
    aTest.TestInteger := lcv;
    aTest.TestString  := IntToStr( lcv );
  end;
  aTests.SaveToFile( 'C:\Test.txt' );
  FreeAndNil( aTests );
end;

procedure TForm1.btnButton2Click(Sender: TObject);
var
  aTests : TTests;
  lcv    : Integer;
begin
  aTests := TTests.Create( Self, TTest );
  aTests.LoadFromFile( 'C:\Test.txt' );
{$IFDEF CODESITE}
  CodeSite.SendObject( 'aTests', aTests );
  for lcv := 0 to pred( aTests.Count ) do
  begin
    CodeSite.SendInteger( 'aTest[' + IntToStr( lcv ) + '].TestInteger', TTest(aTests.Items[ lcv ]).TestInteger );
    CodeSite.SendString( 'aTest[' + IntToStr( lcv ) + '].TestString', TTest(aTests.Items[ lcv ]).TestString );
  end;
{$ENDIF}
  FreeAndNil( aTests );
end;

{ TTest }

procedure TTest.Assign(Source: TPersistent);
begin
  if ( Source is TTest ) then
  begin
    Self.TestInteger := TTest( Source ).TestInteger;
    Self.TestString := TTest( Source ).TestString;
  end
  else
    inherited;
end;

end.
0
StefaanCommented:
bleh, too late again :-P
0
boardtcAuthor Commented:
Sorry you were late Stefaan, I have however converted to yuor method, much cleaner than the TReader . TWriter method, thank you!

The end result is the same. Any way to make the output clean (like delphi with the dfm). I am going to use it as a quick and dirty way of populating a collection so would like a cleaner file than present.

Cheers, Tom.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.