如何从文件装载 Record 类型的数据(200分)

  • 主题发起人 主题发起人 Always
  • 开始时间 开始时间
A

Always

Unregistered / Unconfirmed
GUEST, unregistred user!
我在程序开头的类型结构定义可如下表示:

TMyCustomClass = class of TComponent;

TAdventRecord = record
f: Integer;
c: TMyCustomClass;
x: Integer;
y: Integer;
end;

const
AdventTable: array[0..99] of TAdventRecord =
(
(f: 100; c: TButton; x: 0; y: 120),
(f: 110; c: TLabel; x: 0; y: 240),
(f: 120; c: TImage; x: 0; y: 480),
......(更多的)
);

但我希望 TAdventRecord 的数据可以事先独立存储于一个文件中,
随时如 LoadFrom...一样被地加载.

自当重谢!!!
 
type
F: file of TAdventRecord;
A: TAdventRecord;

以后就可以
assignFile(F,"aaa.dat");
reset(F, 1);

然后用read(F, A);来读
 
>assignFile(F,"aaa.dat");
>reset(F, 1);
^^^
是用
reset(F,sizeof(TAdventRecord));
吧?
 
没这么简单. advrecord.c (TMyCustomClass)项需要单独处理, 否则写进去的是个地址值(32 bit).
读时就成了个无效指针(原来指向的东西都没保存过!).
 
好象没问题,在Pascal中就是这样!
可以把记录作为一个元素直接读写。
(直接reset(F)就行了。)
不放心就用Blockread/Blockwrite吧。
procedure BlockRead(var F: File; var Buf; Count: Integer [; var AmtTransferred: Integer]);

 
AdventTable: array[0..99] of TAdventRecord =
(
(f: 100; c: TButton; x: 0; y: 120),
(f: 110; c: TLabel; x: 0; y: 240),
(f: 120; c: TImage; x: 0; y: 480),
......(更多的)
);

这样定义不对吧? TButton, TLabel, TImage都是类, 不是对象实例. 应该为某一具体
对象实例才对.

要保存或读出您这样的结构很麻烦, 得直接操作typeinfo表才能得到c的内容(等于写个delphi IDE). 或者用 类似:
if adventtable.c is TWinControl then ....
else if adventtable.c is TGraphyControl then ....
else .....
这样的语句才能保存. 读出一样麻烦.
 
噢,
我搞错了一点!
记录中的对象是无效的!
 
>>好象没问题,在Pascal中就是这样!
>>可以把记录作为一个元素直接读写。
记录是可以直接读写, 但记录中的指针, 类, 字符串...这些非简单变量内容具体存放的地方可不在
记录中, 记录中保存的只是一个指向具体内存的指针.
所以光直接写记录, 所有记录中的指针, 类, 字符串的内容都将丢失. 读取时只能读到一个指向
无效地址的指针.
 
Another_eYes:
多谢提醒!
我也刚想到这个问题!

对于对象的处理,要么不处理!(可能不合要求)
要么就连同对象信息一起保存下来!
就象.dfm文件的文本格式一样!
自己写个加载函数,
在处理对象时,先由对象信息生成对象,再将对象的指针赋给c,
不过最后注意释放.
其它内容照读.
 
Another_eYes:

const
AdventTable: array[0..99] of TAdventRecord =
(
(f: 100; c: TButton; x: 0; y: 120),
(f: 110; c: TLabel; x: 0; y: 240),
(f: 120; c: TImage; x: 0; y: 480),
......(更多的)
);

其中的 TButton、Tlabel、TImage...只作举例说明之用,实际上
是我的一些自定义类对象。如TMyClass1、TMyClass2...
 
用reset(f)就可以读了
但有一点,append(f)是错误的。
如果要改写记录文件,仍用
reset(f);
seek(f,记录数位置);
write(f,recvar);
 
记录在RTTI没有类型信息,无法根据类型直接读他的定义.
你所提的问题可以用如下方式实现:

TItemClass=class(TPersistent)
private
f:Integer;
c:TComponent;
x:Integer;
y:Integer;
public
property f:Integer ...
property c...
property x...
property y...
end;

TAdventTable=class(TCompoent)
private
FList:TList; //save TItemClass Pointer
proteted
procedure DefineProperties(Filer: TFiler); override;
end;

通过重载DefineProperties实现类的读写,这个过程简单:

下面是分别为 DefineProperties 定义的读写过程(其他略):

procedure TAdventTable.ReadData(Reader:TReader);
var
Item:TItemClass;
begin
Reader.ReadListBegin;
while Not Reader.EofList do begin
Item:=TItemClass.Create;
Item.f:=Reader.ReadInteger;
Item.c:=Reader.ReadComponent;
Item.x:=Reader.ReadInteger;
Item.y:=Reader.ReadInteger;
FList.Add(Item);
end;
end;

procedure TAdventTable.WriteData(Writer:TWriter);
var
Item:TItemClass;
begin
Writer.WriteListBegin;
for i:=0 to FList.Count-1 do begin
Item:=TItemClass(FList);
Writer.WriteInteger(Item.f);
Writer.WriteComponent(Item.C);
Writer.WriteInteger(Item.x);
Writer.WRiteInteger(Item.y);
end;
Writer.WriteListEnd;
end;

以上TAdvanceTable也可定义为TObject,然后分别定义
Read and Write procedure 来读写流(文件存入流,文件中装载流).
 
多人接受答案了。
 

Similar threads

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