Solved

save two TStringList to FileStream

Posted on 2002-04-05
10
2,463 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
ID: 6920782
Sorry for loading parameter is fmOpenRead instead of fmCreate sorry (I just copy it :p )
0
 

Expert Comment

by:classics
ID: 6920838
Save them to seperate files.
0
 
LVL 4

Expert Comment

by:nestorua
ID: 6921114
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
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 

Author Comment

by:comicboy
ID: 6921332
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
ID: 6921522
Try using TInifile then, save each list under a different header (key).
0
 
LVL 4

Expert Comment

by:nestorua
ID: 6921606
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
ID: 6922364
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
ID: 6922519
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
ID: 6922556
nice way with TReader and TWriter :)
0
 

Author Comment

by:comicboy
ID: 6922932
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

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

821 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