Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 645
  • Last Modified:

WriteComponent & ReadComponent with dynamic object arrays...

hello all,
Im hoping someone can help me.
Im saving some objects in my app to a file when it exits, and then reading them back when my app restarts.
Some of the objects are static and some objects are dynamic though.

The code Im listing first works perfectly. It was a test project I made to see if this will work
------------------------------------------------------------------------
var
  F: TFileStream;
  CurDir : String;
  lblTMP : array[0..2] of THTMLabel;

procedure TForm1.btnWriteClick(Sender: TObject);
{ WRITE THE OBJECT TO A FILE VIA STREAM }
var
  i: integer;
begin
  CurDir := ExtractFileDir(Application.ExeName);
  F := TFileStream.Create(CurDir + '\label.dat', fmCreate or fmShareCompat);
  try
    { create a few objects }
    for i := 0 to 2 do
      lblTMP[i] := THTMLabel.Create(nil);
    { add the text to one of the objects }
    with lblTMP[1] do begin
        HTMLText.add("some test to show');
        visible := false;
    end;
    { write the objects (save) }
    for i := 0 to 2 do
      F.WriteComponent(lblTMP[i]);

  finally
    for i := 0 to 2 do
      lblTMP[i].Free;
    F.Free;
  end;
end;

procedure TForm1.btnReadClick(Sender: TObject);
{ READ THE OBJECT FROM A FILE VIA STREAM }
var
  i: integer;
begin
  CurDir := ExtractFileDir(Application.ExeName);
  if FileExists(CurDir + '\label.dat') then begin
    F := TFileStream.Create(CurDir + '\label.dat', fmOpenRead or fmShareDenyWrite);
    try
      for i := 0 to 2 do
        lblTMP[i] := THTMLabel.Create(nil);
      for i := 0 to 2 do
        F.ReadComponent(lblTMP[i]);
      edit2.Text := lblTMP[1].Text;
    finally
      for i := 0 to 2 do
        lblTMP[i].Free;
      F.Free;
    end;
  end;

end;

-------------------------------------------------------------------------
The above code works, but the following does not even though its basically the same
-------------------------------------------------------------------------
type
  TOpenWeekRec = record   { OPEN THIS WEEK }
    trCount    : longint;
    Title      : string[255];
    Link       : string[255];
    RawTitle   : string;
    RawPlayers : string;
    RawPlot    : string;
    RawBuzz    : string;
  end;

  public
    { Public declarations }
    arrOpenWeek : Array of TOpenWeekRec;

var
  arrTMP2 : array of array[0..6] of THTMLabel;
  F: TFileStream;
  CurDir: String;

procedure WriteObjects();
var
  i, x: integer;
begin
  CurDir := ExtractFileDir(Application.ExeName);
  F := TFileStream.Create(CurDir + '\results.dat', fmCreate or fmShareCompat);
  try
    F.WriteComponent(HTMLTreeview1);
    F.WriteComponent(HTMLTreeview2);
    F.WriteComponent(HTMLabel1);
    F.WriteComponent(HTMLabel2);
    { SAVE THE ARRAY COUNT FOR WHEN WE READ IT BACK IN }
    F.Write((arrOpenWeek[0].trCount), sizeof(arrOpenWeek[0].trCount));
    { SAVE DYNAMIC ARRAY NOW }
    SetLength(arrTMP2,arrOpenWeek[0].trCount);
    try
      { CREATE TEMP OBJECTS TO PUT STRINGS INTO }
      x:= 0;
      for i := 0 to high(arrOpenWeek) do
        for x := 0 to 6 do
          arrTmp2[i,x] := THTMLabel.Create(nil);
      { INSERT TEXT INTO THE OBJECTS }
      x:=0;
      for i := 0 to high(arrOpenWeek) do begin
        for x := 0 to 6 do begin
          case x of
            0: arrTmp2[i,x].HTMLText.add(IntToStr(arrOpenWeek[i].trCount));
            1: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].Title);
            2: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].Link);
            3: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].RawTitle);
            4: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].RawPlayers);
            5: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].RawPlot);
            6: arrTmp2[i,x].HTMLText.add(arrOpenWeek[i].RawBuzz);
          end;
        end;
      end;
      { WRITE THE OBJECTS INTO THE STREAM }
      for i := 0 to high(arrTmp2) do
        for x := 0 to 6 do
          F.WriteComponent(arrTmp2[i,x])
    finally
      { DELETE TEMP OBJECTS }
      for i := 0 to high(arrTmp2) do
        for x := 0 to 6 do
          arrTmp2[i,x].free;
    end;
  finally
    F.Free;
  end;
end;

procedure ReadObjects();
var
  count, i, x: integer;
begin
  CurDir := ExtractFileDir(Application.ExeName);
  if FileExists(CurDir + '\results.dat') then begin
    F := TFileStream.Create(CurDir + '\results.dat', fmOpenRead or fmShareDenyWrite);
    try
      F.ReadComponent(HTMLTreeview1);
      F.ReadComponent(HTMLTreeview2);
      F.ReadComponent(HTMLabel1);
      F.ReadComponent(HTMLabel2);
      F.Read(count,1) ;
      { LOAD DYNAMIC ARRAY NOW }
      SetLength(arrTmp2, count);
      try
        { CREATE TEMP OBJECTS TO STORE THE STRINGS }
        for i := 0 to high(arrOpenWeek) do
          for x := 0 to 6 do
            arrTmp2[i,x] := THTMLabel.Create(nil);
        { READ THE OBJECT INTO THE TEMP OBJECT }
        for i := 0 to high(arrTmp2) do
          for x := 0 to 6 do
            F.ReadComponent(arrTmp2[i,x])  { <- ERROR OCCURS HERE!!}
      finally
      { DELETE TEMP OBJECTS }
        for i := 0 to high(arrTmp2) do
          for x := 0 to 6 do
            arrTmp2[i,x].free;
      end;
    finally
      f.Free;
    end;
  end;
end;

--------------------------------------------------
There are no problems saving the objects, just reading them.
The error always shows up when I -> F.ReadComponent(arrTmp2[i,x])
EReadError "Invalid stream format"

Like I said, the 1st prj code works, but not the 2nd.
And the only real difference between them is the use of a multi-dimensional array and a record.

thanx for any help
0
LMuadDIb
Asked:
LMuadDIb
  • 2
1 Solution
 
Slick812Commented:
hello  LMuadDIb, I do not have time right now to get your code and run it, to see what is problem, , but from looking at it, I can see something that I know would not work for me in code that I have written for file stream reads, , , your line -

F.Read(count,1) ;

is NOT CORRECT

should it be

F.Read(count,4) ; // count is integer, which is 32 bits (4 bytes)

or more better

F.Read(count, SizeOf(count)) ;

you might add a line to test the value

F.Read(count, SizeOf(count)) ;
if count <> 6 then ShowMessage('Not Six');
0
 
Slick812Commented:
also, here is the addy for a web page which has some info about reading and writting to a TFileStream for delphi

http://www.angelfire.com/hi5/delphizeus/customfiles.html
0
 
LMuadDIbAuthor Commented:
thanx  for the help Slick812 :)
and nice link too
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now