Solved

save two TStringList to FileStream

Posted on 2002-04-05
10
2,416 Views
Last Modified: 2008-02-01
I have 2 TStringList

m_Text: TStringList;
m_Info: TStringList;

I have this text in m_Text :
"Text1"
"Text2"

and I have this text in m_Info :
"Info1"
"Info2"

I save it like this :

var
  Stream: TFileStream;

Stream := TFileStream.Create('Filename', fmCreate);
m_Text.SaveToStream(Stream);
m_Info.SaveToStream(Stream);
Stream.Free;

then I load it :

var
  Stream: TFileStream;

Stream := TFileStream.Create('Filename', fmCreate);
m_Text.LoadFromStream(Stream);
m_Info.LoadFromStream(Stream);
Stream.Free;

But instead of having text each like above I have the m_Text hold all of the text while m_Info is empty.

How to fix it ?
0
Comment
Question by:comicboy
  • 3
  • 2
  • 2
  • +3
10 Comments
 

Author Comment

by:comicboy
Comment Utility
Sorry for loading parameter is fmOpenRead instead of fmCreate sorry (I just copy it :p )
0
 

Expert Comment

by:classics
Comment Utility
Save them to seperate files.
0
 
LVL 4

Expert Comment

by:nestorua
Comment Utility
HI, comicboy,
If you have both of the StringLists with the same "Count"
property (as in your example), you have to do the following:
//
procedure ReadFromFile(const FileName: string);
var SL: TStringList;
begin
SL:=TStringList.Create;
with SL do
try
LoadFromFile(FileName);  
m_Text.Clear;
for i:=0 to (Count div 2)-1 do
m_Text.Add(SL[i]);
m_Info.Clear;
for i:=(Count div 2) to Count-1 do
m_Info.Add(SL[i]);
finally
Free;  
end;
end;
//
procedure WriteToFile(const FileName: string);
var SL: TStringList;
begin
SL:=TStringList.Create;
with SL do
try
AddStrings(m_Text);
AddStrings(m_Info);
SaveToFile(FileName);  
finally
Free;  
end;
end;
Sincerely,
Nestorua.
0
 

Author Comment

by:comicboy
Comment Utility
Hi classic, I think I know if I should separate it into 2 files :p hehehe but I need it within one file which infact I combine the file with another data too like bitmap and other data.

for Nestorua, the problem is both may have different count. But I think I can also add an integer header for each which let me know how many entry within each TStringList. I may try to program it...
0
 

Expert Comment

by:classics
Comment Utility
Try using TInifile then, save each list under a different header (key).
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 4

Expert Comment

by:nestorua
Comment Utility
HI, comicboy,
If you have them with different counts, then you can save them in TStream writing first there counts.
But the more elegant way is to use TReader and TWriter with
ReadListBegin, ReadListEnd, WriteListBegin and WriteListEnd methods.
Sincerely,
Nestorua.
0
 
LVL 1

Accepted Solution

by:
MBo earned 50 total points
Comment Utility
hi, comicboy
2 ways

1) saving
FS:TFileStream;
MS:TMemoryStream;

ms:= TMemoryStream.Create;
fs:= TFileStream.Create('e:\file.dat',fmCreate);

m_Text.SaveToStream(ms);
ms.Position := 0;
size := ms.Size;
fs.WriteBuffer( size, Sizeof(size));
fs.CopyFrom(ms, size );
ms.Clear;

m_Info.SaveToStream(ms);
ms.position := 0;
size := ms.Size;
fs.WriteBuffer( size, Sizeof(size));
fs.CopyFrom(ms, size );

ms.Free;
fs.Free;

loading

ms:= TMemoryStream.Create;
fs:= TFileStream.Create('e:\file.dat',fmOpenRead);

fs.ReadBuffer( size, sizeof(integer));
ms.CopyFrom(fs, size );
ms.Position := 0;
m_Text.LoadFromStream(ms);

ms.Clear;
fs.ReadBuffer( size, sizeof(integer));
ms.CopyFrom(fs, size );
ms.Position := 0;
m_Info.LoadFromStream(ms);

ms.Free;
fs.Free;

2) saving
fs:TFileStream;
size:integer;
s:string;

fs:= TFileStream.Create('e:\file.dat',fmCreate);

size:=length(m_text.CommaText);
fs.Write(size,sizeof(integer));
s:=m_text.CommaText;
fs.Write(s[1],size);

size:=length(m_info.CommaText);
fs.Write(size,sizeof(integer));
s:=m_info.CommaText;
fs.Write(s[1],size);

fs.free;

loading

fs:= TFileStream.Create('e:\file.dat',fmOpenRead);

fs.Read(size,sizeof(integer));
setlength(s,size);
fs.Read(s[1],size);
m_text.CommaText:=s;

fs.Read(size,sizeof(integer));
setlength(s,size);
fs.Read(s[1],size);
m_Info.CommaText:=s;

fs.free;

Both methods work fine.
Of course, don't forget to create StringLists
0
 
LVL 10

Expert Comment

by:Jacco
Comment Utility
Another nice way:

procedure SaveStringLists(aStream: TStream; const aLists: array of TStrings);
var
  lW: TWriter;
  liList: Integer;
begin
  lW := TWriter.Create(aStream, 256);
  try
    lW.WriteListBegin;
    for liList := Low(aLists) to High(aLists) do
    begin
      lW.WriteString(aLists[liList].Text);
    end;
    lW.WriteListEnd;
  finally
    lW.Free;
  end;
end;

procedure LoadStringLists(aStream: TStream; const aLists: array of TStrings);
var
  lR: TReader;
  liList: Integer;
begin
  lR := TReader.Create(aStream, 256);
  try
    liList := Low(aLists);
    lR.ReadListBegin;
    while not lR.EndOfList do
    begin
      if liList <= High(aLists) then
        aLists[liList].Text := lR.ReadString;
      Inc(liList);
    end;
    lR.ReadListEnd;
  finally
    lR.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  lFS: TFileStream;
begin
  lFS := TFileStream.Create('d:\test.sls', fmCreate);
  try
    SaveStringLists(lFS, [Memo1.Lines, Memo2.Lines]);
  finally
    lFS.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  lFS: TFileStream;
begin
  lFS := TFileStream.Create('d:\test.sls', fmOpenRead);
  try
    LoadStringLists(lFS, [Memo1.Lines, Memo2.Lines]);
  finally
    lFS.Free;
  end;
end;

This alse works with stringlists.

Regards Jacco
0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
nice way with TReader and TWriter :)
0
 

Author Comment

by:comicboy
Comment Utility
I think I I've better use the way MBo did (the 2nd one) since it's most closely what actually I need, even though it's not as sophiticated as using TReader and TWriter, but it's conventional and simplistic I do undestand, so sorry I'm newbies in Delphi.

While I also need to place several other data like TBitmap within single TFileStream (so the file may contain : arbitrary length text, record of data and several bitmaps) and so I can't use TINI file.

Thanks to all experts who trying to help you are all great and the best "MAHA GURU" in this world I know :)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now