有没有 Delphi 序列化库可以序列化记录和记录数组而不是类?
@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 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 5到XE2之间使用,可以在我们的一个开源单元中找到。
实际上,它实现了以下功能:
RecordEquals, RecordSave, RecordSaveLength, RecordLoad
;TDynArray
对象,它是任何动态数组的包装器,能够围绕任何动态数组公开类似TList的方法,甚至包含记录、字符串或其他动态数组。它能够序列化任何动态数组。序列化使用优化的二进制格式,并能够将任何记录或动态数组保存和加载为RawByteString
。你还可以使用JSON序列化,包括自定义布局 - 参见记录的自定义JSON序列化。
作为一条记录,如果你没有属性,我不认为你会更进一步,尝试使用任何持久性框架(如DeHL)。
虽然技术上正确,但接受的答案在现实世界中的效用是可疑的,并且如果您在生产中使用它,会有许多长期支持噩梦的情况。不要这样做。
如果您的程序只是一些特定的需求,我谨虔地建议您使用“文件记录”,这是一种经典的Turbo Pascal技术,仍然有效。