Delphi语言如何对自定义类进行持久化保存及恢复 (性能远比json/xml高)

        Delphi的RTL自身就带有一套很好的资源持久化保存(IDE设计窗体时,保存为DFM格式及编译到EXE里面的资源文件)及恢复机制(EXE启动时对窗体资源的加载),那么应没必要再额外用xml/json格式保存程序的参数了,我们大可以将参数集中在一个参数类里面,然后通过这套机制进行保存及恢复。

        由于我们的参数类型可能五花八门,除了传统的整数、小数、字符串、true/false、还有可能是数组、列表、枚举等,则需要override DefineProperties这个函数来自定义属性的保存及恢复。

        废话少说,给出代码,此代码演示了如何自定义数据的保存及恢复、以及保存整个Form:

	unit Unit1;

	interface

	uses
	  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
	  Vcl.Graphics,
	  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

	type
	  TArrayOfInteger = array of integer;

	  TSetting = class(TComponent)
	  private
		fIntVal: integer;
		fIntArr: TArrayOfInteger;
		procedure ReadIntArr(Reader: TReader);
		procedure WriteIntArr(Writer: TWriter);
	  protected
		procedure DefineProperties(Filer: TFiler); override;
	  public
		property intArr: TArrayOfInteger read fIntArr write fIntArr;

	  published
		property intval: integer read fIntVal write fIntVal;
	  end;

	  TForm1 = class(TForm)
		btnCloneClass: TButton;
		mmo1: TMemo;
		btnCloneForm: TButton;
		procedure btnCloneClassClick(Sender: TObject);
		procedure btnCloneFormClick(Sender: TObject);
	  private
		{ Private declarations }
	  public
		{ Public declarations }
	  end;

	var
	  Form1: TForm1;

	implementation

	{$R *.dfm}
	{ TSetting }

	procedure TSetting.DefineProperties(Filer: TFiler);
	begin
	  inherited;
	  Filer.DefineProperty('intArr', ReadIntArr, WriteIntArr, true);
	end;

	procedure TSetting.ReadIntArr(Reader: TReader);
	var
	  lvIdx: integer;
	begin
	  fIntArr := nil;
	  Reader.ReadListBegin;
	  SetLength(fIntArr,Reader.ReadInteger);
	  lvIdx:=low(fIntArr);
	  while not Reader.EndOfList do
	  begin
		fIntArr[lvIdx] := Reader.ReadInteger;
		inc(lvIdx);
	  end;
	  Reader.ReadListEnd;
	end;

	procedure TSetting.WriteIntArr(Writer: TWriter);
	var
	  i: integer;
	begin
	  Writer.WriteListBegin;
	  Writer.WriteInteger(integer(Length(fIntArr)));
	  for i := Low(fIntArr) to High(fIntArr) do
	  begin
		Writer.WriteInteger(fIntArr[i]);
	  end;
	  Writer.WriteListEnd;
	end;

	function ClassToStr(pvClass: TComponent): ansiString;
	var
	  inStream, outStream: TMemoryStream;

	begin
	  inStream := TMemoryStream.Create;
	  outStream := TMemoryStream.Create;
	  try
		inStream.WriteComponentRes(pvClass.ClassName, pvClass);
		// inStream.WriteComponent(pvClass);
		inStream.Position := 0;
		ObjectResourceToText(inStream, outStream);
		// ObjectBinaryToText(inStream,outStream);
		outStream.Position := 0;
		SetLength(Result, outStream.Size + 1);
		FillChar(Result[1], outStream.Size + 1, 0);
		outStream.ReadBuffer(Result[1], outStream.Size);
	  finally
		FreeAndNil(inStream);
		FreeAndNil(outStream);
	  end;
	end;

	function StrToClass(pvStr: ansiString; pvCmpToSetProperties: TComponent=nil): TComponent;
	var
	  inStream, outStream: TMemoryStream;
	begin
	  inStream := TMemoryStream.Create;
	  outStream := TMemoryStream.Create;
	  try
		if (pvStr <> '') then
		  inStream.WriteBuffer(pvStr[1], length(pvStr));
		inStream.Position := 0;
		ObjectTextToResource(inStream, outStream);
		// ObjectTextToBinary(inStream,outStream);
		outStream.Position := 0;
		Result := outStream.ReadComponentRes(pvCmpToSetProperties);
	  finally
		FreeAndNil(inStream);
		FreeAndNil(outStream);
	  end;

	end;

	procedure TForm1.btnCloneClassClick(Sender: TObject);
	var
	  lvObj, lv1: TSetting;
	  lvStr: String;
	  lvArr: TArrayOfInteger;
	begin
	  lvObj := TSetting.Create(nil);
	  try
		lvObj.intval := 12345;
		SetLength(lvArr, 3);
		lvArr[0] := 222;
		lvArr[1] := 333;
		lvArr[2] := 444;
		lvObj.intArr := lvArr;
		lvStr := ClassToStr(lvObj);
		RegisterClass(TSetting);
		lvObj.intval := 1;
		lv1 := TSetting(StrToClass(lvStr, nil));
		if (lv1.intval > lvObj.intval) then
		  mmo1.Text := lvStr;
	  finally
		FreeAndNil(lvObj);
		FreeAndNil(lv1);
	  end;
	  // WriteComponentResFile(ExtractFilePath(ParamStr(0))+ 'd.res',self);
	end;

	procedure TForm1.btnCloneFormClick(Sender: TObject);
	var lvNewForm:TForm1;
	lvRes:string;
	begin
	  lvRes:=ClassToStr(self);
	  RegisterClass(TForm1);
	  lvNewForm:=TForm1.CreateNew(application);
	  StrToClass(lvRes,lvNewForm);
	  lvNewForm.Left:=self.Left+50;
	  lvNewForm.Top:=self.Top+50;

	end;

	end.
	
	


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Delphi是一种集成开发环境(IDE),被用于创建Windows平台上的应用程序。在Delphi中,我们可以使用自定义来创建自己的数据型和对象。 自定义是用于封装数据和功能的模块化单元。通过自定义,我们可以将相关的数据和方法组织在一起,以便更好地管理和操作。一个自定义可以包含属性(对应数据)、方法(对应功能)和事件(对应触发器)。 在Delphi中,我们可以使用向导来创建自定义向导提供了一个可视化界面,可以设置的属性和方法。首先,我们可以定义的名称、父(如果有)、接口(可选)等。然后,我们可以添加属性或方法,并为它们设置数据型、访问修饰符和实现代码。最后,我们可以根据需要为添加事件。 通过自定义,我们可以创建多个对象,每个对象都具有相同的属性和方法,但它们的数据可以独立进行操作。我们可以在代码中通过实例化来创建对象,并访问对象的属性和方法。 自定义Delphi中具有许多优点。首先,它提了代码的可维护性和可读性,因为相关的数据和功能被组织在一起。其次,它提供了代码的重用性,因为我们可以在不同的应用程序中使用相同的。另外,自定义还支持面向对象编程的特性,如继承、封装和多态,使得我们可以更加灵活地设计和实现程序。 总之,Delphi自定义是一种强大的工具,可以帮助我们创建模块化、可维护和灵活的应用程序。通过向导,我们可以轻松地创建自定义,并利用它们来封装数据和功能,提代码的可读性和重用性。 ### 回答2: Delphi是一种面向对象的编程语言,可以使用它来创建自定义自定义是指根据程序需求,开发者可以创建自己定义的数据型。 在Delphi中,我们可以使用class关键字来定义一个。一个由一组属性和方法组成。属性是的数据成员,用于存储和表示对象的状态。方法是用于对对象进行操作和执行特定功能的函数。 在定义时,需要考虑的属性和方法。可以根据需要添加需要的属性,每个属性都有其型和访问权限。属性的型可以是基本数据型,如整数、浮点数、字符等,也可以是其他自定义的方法定义了的行为和功能,可以包括对属性的读取和设置、对象的初始化和析构等操作。方法可以是公共方法,可以在的外部访问和调用;也可以是私有方法,只能在的内部访问和调用。 自定义的一个好处是可以根据需要封装和组织数据和功能,提代码的可读性和可维护性。通过自定义,可以建立具有相关属性和方法的对象实例,简化程序的设计和开发过程。 在Delphi中,可以使用自定义来实现各种功能,如创建游戏角色、管理学生信息、处理文件操作等。通过定义各种属性和方法,可以使适应不同的应用场景,并实现灵活的功能。 总的来说,Delphi自定义功能十分强大,可以根据需求创建各种数据型并封装相关的操作,提程序的可扩展性和可维护性。通过自定义,可以实现更加灵活和效的编程。 ### 回答3: Delphi 是一种级的编程语言,它允许开发人员创建自定义来实现特定功能和逻辑。自定义是面向对象编程的基本概念之一,它允许开发人员将相关的数据和方法组织在一起,以便更好地管理和重用代码。 在 Delphi 中创建自定义的过程非常简单,只需要按照一定的语法规则来定义的成员即可。自定义可以包含属性、方法和事件等成员。 属性是的特征或状态,可以通过访问器(Getter)和修改器(Setter)来读取和修改属性的值。方法是的行为,用于执行特定的操作或完成特定的任务。事件是的响应机制,可以在特定的情况下触发特定的操作。 使用自定义可以让开发人员更好地组织和管理代码,并且提代码的重用性。当我们需要实现某项特定功能时,只需要创建一个适应需求的自定义,并调用的成员来实现相关的功能。 例如,我们可以创建一个自定义来表示一个学生,该可以包含学生的姓名、年龄和成绩等属性,还可以包含计算学生平均成绩的方法。当我们需要计算一个学生的平均成绩时,只需要创建一个学生对象,并调用平均成绩的计算方法即可。 总之,Delphi 提供了强大的功能来创建自定义,使开发人员能够更好地组织和管理代码,并提代码的可读性和可维护性。通过合理地使用自定义,我们可以更加效地开发出符合需求的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值