We help IT Professionals succeed at work.

Component Variable writen to a Stream

rafaelri
rafaelri asked
on
I've written a component (derived from TComponent) and I have a variable in the component that I wanted to be saved (and also retrieved after) with a stream component (TMemoryStream for eg) but I could only do this declaring a published property and I don't want the variable to be visible outside the component.
Comment
Watch Question

Commented:
Well, If your component is fairly simple you could try something like this (_very_) ugly hack, but I'd like to see something better myself:



  TMyComponent = class(TComponent)
  private
     FInt : integer;
  public
  end;

var
  Form1: TForm1;
  compA,compB : TMyComponent;

procedure TForm1.FormCreate(Sender: TObject);
var
   ms : TMemoryStream;
   result : string;
begin
     compa := TMyComponent.create(self);
     compa.FInt := 1234;
     compb := TMyComponent.create(self);
     move(pointer(compa)^,pointer(compb)^,compa.InstanceSize);
     caption := intToStr(compa.FInt)+','+intToStr(compb.FInt);
     compa.free;
     compb.Free;
end;


GL
Mike
CERTIFIED EXPERT
Top Expert 2004

Commented:
from the delphihelp

function ComponentToString(Component: TComponent): string;

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    StrStream := TStringStream.Create(s);
    try
      BinStream.WriteComponent(Component);
      BinStream.Seek(0, soFromBeginning);
      ObjectBinaryToText(BinStream, StrStream);
      StrStream.Seek(0, soFromBeginning);
      Result:= StrStream.DataString;
    finally
      StrStream.Free;

    end;
  finally
    BinStream.Free
  end;
end;

function StringToComponent(Value: string): TComponent;
var
  StrStream:TStringStream;
  BinStream: TMemoryStream;
begin
  StrStream := TStringStream.Create(Value);
  try
    BinStream := TMemoryStream.Create;
    try
      ObjectTextToBinary(StrStream, BinStream);
      BinStream.Seek(0, soFromBeginning);
      Result := BinStream.ReadComponent(nil);

    finally
      BinStream.Free;
    end;
  finally
    StrStream.Free;
  end;
end;

meikl ;-)

Commented:
Hmmm, you can see the "extra" ms : TMemoryStream declartion in my example.  Firts off I _tried_ to use Write/ReadComponent but the only way it would copy the private member was if there was also a published property with both read & write handlers that accessed the private member.

GL
Mike
Commented:
This is how to stream a non-published property from design time.

Read my 2 articles on writing components at www.howtodothings.com


procedure DefineProperties(Filer: TFiler); override;
procedure ReadMyProp(Source: TStream);
procedure WriteMyProp(Dest: TStream);

implementation

procedure TMyComp.DefineProperties(Filer: TFiler);
begin
  inherited;
  Filer.DefineBinaryProperty('MyPropName', ReadMyProp, WriteMyProp, True);
end;


Pete
====
http://www.HowToDoThings.com (delphi articles)
http://www.Stuckindoors.com/delphi (Open source Delphi)
procedure TForm1.ReadMyProp(Source: TStream);
begin
  Source.Read(FMyProp, SizeOf(Integer))
end;

procedure TForm1.WriteMyProp(Dest: TStream);
begin
  Dest.Write(FMyProp, SizeOf(Integer));
end;

Commented:
cubud's suggestion to override TPersistent's DefineProperties is cool.

I seem to remember Read/WriteProperties methods you can also override. I think they're methods of TComponent (?), similar to the DefineProperties/WriteProp/ReadProp combination, only shorter.

Commented:
I don't think there is.  TPersistent does not read / write its own properties, that is the job of a TReader / TWriter.

TPersistent.DefineProperties is called by the reader / writer to ask the object if it has any additional properties it wishes to declare.

Pete
====
http://www.HowToDoThings.com (delphi articles)
http://www.Stuckindoors.com/delphi (Open source Delphi)

Commented:
I stand humbly corrected.

Commented:
I stand humbly corrected.

Author

Commented:
cubud, I'm gonna try it! :) if it works the points are yours. also a bit more than the current 50 (for the urls! by the way, do you have anymore? :))

Author

Commented:
Cubud, let me explain better what I'm trying to do. I've created a component to handle user passwords (cryptography and authentication stuff). And it has a method setPass and another checkPass, the first sets the password and the second is used when the user is trying to logon, so it verifies if the typed password is correct. I want to save the whole component (including the private variable that stores the crypted password) into a blob field in a table. So, how is the best way that I can implement it into the component? without having to let the cryptographed password visible outside the component (like a published property).

Author

Commented:
Cubud, what an article you've written. It's excellent!!

Commented:
To write it

var
  FS: TFileStream;
  Writer: TWriter;
begin
  FS := TFileStream.Create('c:\somefile.txt', fmCreate);
  Writer := TWriter.Create(FS, 4096);
  try
    Writer.WriteRootComponent(MyComponent);
  finally
    Writer.Free;
    FS.Free;
  end;
  TBlobField(MyTable.FieldByName('MyField')).LoadFromFile('c:\somefile.txt');
end;

to read it
var
  FS: TFileStream;
  Reader: TReader;
  Temp: TComponent;
begin
  TBlobField(MyTable.FieldByName('MyField')).SaveToFile('c:\somefile.txt');
  Temp := MyComponentOnMyForm;
  FS := TFileStream.Create('c:\somefile.txt', fmOpenRead);
  Reader := TReader.Create(FS, 4096);
  try
    Reader.ReadRootComponent(Temp); //not MyComponentOnMyForm !!
  finally
    Reader.Free;
    FS.Free;
  end;
end;

That is how to read / write a component from / to a stream.
Use the code I posted previously if you additionally want it to read / write a properties that are not published.

As for the sites, those are mine and they are the only 2 I have !

Pete
====
http://www.HowToDoThings.com (delphi articles)
http://www.Stuckindoors.com/delphi (Open source Delphi)

Author

Commented:
Cubud, I've a problem, I've a property that is a array of integer, how can I save it??? I tried to use the writebuffer method but it really screwed up everything. Can you post me an example?!?

Author

Commented:
Cubud, I found how to write the array, I used writelist and readlist! tks a lot!

Explore More ContentExplore courses, solutions, and other research materials related to this topic.