【发布时间】:2010-06-06 13:38:25
【问题描述】:
是否有任何 Delphi 序列化库能够序列化记录和记录数组而不是类?
【问题讨论】:
标签: delphi serialization
是否有任何 Delphi 序列化库能够序列化记录和记录数组而不是类?
【问题讨论】:
标签: delphi serialization
@Max 你可以使用JEDI 中的TJvAppXMLFileStorage 组件来序列化一条记录或一组记录。
您可以使用名为WriteBinary 的过程来存储数据并使用ReadBinary 来读取数据。
不幸的是,关于这个组件的文档不多,所以这里有一个非常简单的示例来存储单个记录(对于记录数组,您可以轻松修改此源代码)。
type
MyRecord= record
Field1 : Integer;
Field2 : Double;
Field3 : String[20];
Field4 : String[20];
end;
Procedure SaveMyRecord(Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
//this component supports store multiples objects to the same file, so you need use an identifier for you particular object, in this case i'm use the Dummy name.
MyStore.WriteBinary('Dummy', @Rec,sizeof(Rec));
MyStore.Xml.SaveToFile(MyStore.FileName);
finally
MyStore.Free;
end;
end;
这个程序创建一个像这样的XML文件,数据以十六进制格式编码。
<?xml version="1.0" encoding="iso-8859-1"?>
<Configuration>
<Dummy>84030000000000003333333333331F400D737472696E6720746573742031000000000000000D737472696E672074657374203200000000000000000000000000</Dummy>
</Configuration>
Procedure LoadMyRecord(var Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';//point to the same file
MyStore.Xml.LoadFromFile(MyStore.FileName); //load the file
MyStore.ReadBinary('Dummy', @Rec,sizeof(Rec));//use the Dummy identifier and pass the record as an pointer
finally
MyStore.Free;
end;
end;
program ProjectPersistRecord;
{$APPTYPE CONSOLE}
uses
SysUtils,
JvAppXMLStorage;
type
MyRecord= record
Field1 : Integer;
Field2 : Double;
Field3 : String[20];
Field4 : String[20];
end;
Procedure SaveMyRecord(Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
MyStore.WriteBinary('Dummy', @Rec,sizeof(Rec));
MyStore.Xml.SaveToFile(MyStore.FileName);
finally
MyStore.Free;
end;
end;
Procedure LoadMyRecord(var Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
MyStore.Xml.LoadFromFile(MyStore.FileName);
MyStore.ReadBinary('Dummy', @Rec,sizeof(Rec));
finally
MyStore.Free;
end;
end;
Var
Rec : MyRecord;
begin
//Fill the record
Rec.Field1:=900;
Rec.Field2:=7.8;
Rec.Field3:='string test 1';
Rec.Field4:='string test 2';
SaveMyRecord(Rec); //save the record
FillChar(Rec,SizeOf(Rec),#0); //clear the record variable
LoadMyRecord(Rec);//restire the record data
//show the loaded data
Writeln(rec.field1);
Writeln(rec.field2);
Writeln(rec.field3);
Writeln(rec.field4);
Readln;
end.
【讨论】:
如果你有 Delphi 2010,你可能想看看DeHL。它包含一个序列化库,可以处理几乎任何数据类型。
【讨论】:
另一个解决方案,从 Delphi 5 到 XE2,可用in one of our OpenSource unit。
其实它实现了:
RecordEquals, RecordSave, RecordSaveLength, RecordLoad;TDynArray 对象,它是任何动态数组的包装器,能够在任何动态数组周围公开类似TList 的方法,甚至包含记录、字符串或其他动态数组。它能够序列化任何动态数组。序列化使用优化的二进制格式,并且能够以RawByteString 保存和加载任何记录或动态数组。您还有 JSON 序列化,包括自定义布局 - 请参阅 sustom JSON serialization of records。
【讨论】:
作为一个记录,如果你没有属性,我不相信你会走得更远,尝试使用任何持久性框架(如 DeHL)。
公认的答案虽然在技术上是正确的,但在现实世界的实用程序中是可疑的,并且如果您在生产环境中使用它,它会有许多长期支持——噩梦般的场景。不要这样做。
如果您的程序只是一个临时性的程序,我可以谦虚地建议您使用“记录文件”(一种仍然有效的经典 Turbo Pascal 技术)来使用老式的方法。
【讨论】:
File Of Record old-school 或简单的记录二进制写入到流直接存储二进制数据相比,存在许多真正的缺点.