如何把Tlist保存为数据流或文件,并可以从数据流或文件中读出数据到Tlist(100分)

  • 主题发起人 主题发起人 ChJK
  • 开始时间 开始时间
C

ChJK

Unregistered / Unconfirmed
GUEST, unregistred user!
如何把Tlist保存为数据流或文件,并可以从数据流或文件中读出数据到Tlist
这是我写的部分代码
type
PClips = ^TClips;
TClips = record
cf: Word;
buf: Pointer;
size: Cardinal;
end;
{把Tlist保存成文件,不知道对不对,请指教}
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
blk: PClips;
lipList: TList;
ms: TMemoryStream;
begin
ClipList := TList.Create;
ms := TMemoryStream.Create;
for i := 0 to Clipboard.FormatCount - 1 do
begin
New(blk);
blk.cf := Clipboard.Formats;
GetClippedData(blk.cf, blk.buf, blk.size);
ClipList.Add(blk);
ms.Write(PClips(ClipList.Items^ ), SizeOf(PClips));
end;
ms.SaveToFile('c:/test.dat');
ms.Free;
end;
{把文件内容保存到Tlist,有问题就不贴出来了}
先谢谢各位兄弟了
 
终于将此问题解决了,愿与大家共分享,并希望得到高手的指点
{自定义类型}
type
TestType = ^TTestType;
TestType = record
cf: Word;//格式
buf: TMemoryStream;//数据
size: Cardinal;//数据大小
end;

假定ListTest为TList类型,并已经被赋值,保有TestType类型数据

procedure TListSaveFile(ListTest:TList);//通过数据流保存Tlist数据
var i: Integer;
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
for i:=0 to ListTest.Count -1 do
begin
ms.Writebuffer(TestType(ListTest.Items).cf,sizeof(word));
ms.Writebuffer(TestType(ListTest.Items).size,sizeof(Cardinal));
ms.CopyFrom(TestType(ListTest.Items).buf,TestType(ListTest.Items).buf.Size);
{注意第三行使用的是CopyFrom函数而不是Writebuffer,我试过用Writebuffer写,当会出现错误,希望得到大家

的指点}
end;
ms.SaveToFile('c:/test.dat');
ms.Free;
ListTest.free;
end;

procedure TListLoadFile(filename:string);
var
blk: TestType;
i:Cardinal;
ms: TMemoryStream;
ListTest: TList;
begin
ms:=TMemoryStream.Create ;
ListTest := TList.Create;
ms.LoadFromFile(filename);
i:=ms.Size;//确定内存块的大小
while ms.Position < i do//不知有没有别的方法判断数据是否已全部读完
begin
New(blk);
ms.readBuffer(blk.cf ,sizeof(word));
ms.readBuffer(blk.size ,sizeof(Cardinal));
blk.buf := TMemoryStream.Create;
blk.buf.CopyFrom(ms,blk.size);//注意这里也是使用CopyFrom函数
CopyStreamToClipboard(blk.cf,blk.buf);
ListTest.Add(blk);//将TestType数据存入ListTest中
end;
ms.free;
ListTest.Free;
end;
 
给你提点建议:
1.书写代码时最好按不同层次增加缩进,以方便阅读和以后修改
2.TStream.Memory指针指向的区域才是流数据存放的地方,因此你要用Writebuffer写,可以改成这样
ms.Writebuffer(TestType(ListTest.Items).buf.Memory^,TestType(ListTest.Items).buf.Size);

3.在保存到文件时先将ListTest.Count保存后,再写ListTest其它数据,读出来时只要一个For循环即可
保存:
ms := TMemoryStream.Create;
ms.writebuffer(ListTest.count, sizeof(ListTest.count);//增加这句,保存列表数
for i:=0 to ListTest.Count -1 do
begin
...
end;
打开时:
ms.LoadFromFile(filename);
ms.ReadBuffer(Cnt, Sizeof(ListTest.count)); //将列表数读取到变量Cnt中,使用Sizeof(ListTest.count))是为了和保存时的一致
for i := 0 to Cnt-1 do
begin
...//读列表数据
end;

按你原来的方式也是可以的,我只是觉得不太好,

4.释放列表时,一定要注意释放数据,否则会有内存泄漏
while ListTest.count > 0 do
begin
TestType(ListTest.Items[0]).buf.Free; //释放Tmemorystream对象
Dispose(ListTest.Items[0]); //释放TestType结构
ListTest.Delete(0);
end;
ListTest.Free;

5.Sizeof()参数改成相关变量更好些,这样你一但要更改数据类型时,可以不改Sizeof()参数代码
ms.readBuffer(blk.cf ,sizeof(blk.cf)); //Word改成blk.cf
ms.readBuffer(blk.size ,sizeof(blk.size));//Cardinal改成blk.size
 
to:Tonmy,谢谢你的建议,虚心接受,我会改正错误的
 
接受答案了.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部