Delphi - 无法保存/加载TObjectList到FileStream [英] Delphi - Unable to save/load TObjectList to FileStream

查看:121
本文介绍了Delphi - 无法保存/加载TObjectList到FileStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个TObjectList,我试图写到磁盘。虽然我最终有一个文件(54字节),当我将FNAME属性值更改为真正长的文件,文件的大小从不改变,我得到nil当我尝试读它。我错了什么是错的。对于长代码段很抱歉。它很容易理解发生了什么,只是我不知道为什么它不做我想要的。

 类型
{声明一个新的对象类型。 }
TNewObject = class(TComponent)
private
FName:String;
public
属性BizName:String read FName write FName;
constructor Create(const AName:String);
destructor Destroy();覆盖;
end;

为我的TObjectList声明一个全局变量

  var 
Form1:TForm1;
List:TObjectList< TNewObject> ;;

声明我的构造函数和析构函数。

 构造函数TNewObject.Create(const AName:String); 
begin
FName:= AName;
end;

destructor TNewObject.Destroy;
begin
inherited;
end;

现在添加一个按钮创建我的对象...

  procedure TForm1.CreateButtonClick(Sender:TObject); 
var
Obj:TNewObject;
begin
{创建一个新的列表。 }
{OwnsObjects属性默认设置为true - 列表将自动释放拥有的对象。 }
List:= TObjectList< TNewObject> .Create();

{将一些项添加到列表中。 }
List.Add(TNewObject.Create('One'));
List.Add(TNewObject.Create('Two'));

{添加一个新项目,但保留引用。 }
Obj:= TNewObject.Create('Three');
List.Add(Obj);
end;

现在添加一个SAVE按钮

  procedure TForm1.SaveButtonClick(Sender:TObject); 
var
i:Integer;
fs:TfileStream;
begin
if SaveDialog1.Execute then
begin
fs:= TfileStream.Create(SaveDialog1.FileName,fmCreate);
try
for i:= 0 to List.Count - 1 do
begin

ShowMessage(List [i] .BizName);
fs.WriteComponent(TNewObject(List [i]));
end;
finally
fs.Free;
end;
end;
end;

CAVEATS:我知道只有PUBLIC属性将被保存...应该是BIZNAME。这3个条目显示在SHOWMESSAGE当它被保存....



我记得我的课堂注册。

 初始化
RegisterClass(TNewObject);

为了完整起见,这里是我的加载例程...

  procedure TForm1.LoadButtonClick(Sender:TObject); 
var
i:Integer;
fs:TfileStream;
vRecord:TNewObject;
begin
如果OpenDialog1.Execute然后
begin
List.Clear; // clear list
fs:= TfileStream.Create(OpenDialog1.FileName,fmopenRead);
try

while fs.Position< fs.size do
begin
vRecord:= TNewObject(fs.ReadComponent(nil));
ShowMessage(vRecord.FName);
List.Add(vRecord);
end;
finally
fs.Free;
end;
ShowMessage(IntToStr(List.Count));
end;
end;感谢您的帮助。

>



或者你也可以覆盖 DefineProperties 以决定要传送的内容。

  type 
TNewObject = class(TComponent )
private
FName:String;
procedure ReadName(Reader:TReader);
procedure WriteName(Writer:TWriter);
protected
procedure DefineProperties(Filer:TFiler);覆盖;
public
属性BizName:String read FName write FName;
...

procedure TNewObject.ReadName(Reader:TReader);
begin
FName:= Reader.ReadString;
end;

procedure TNewObject.WriteName(Writer:TWriter);
begin
Writer.WriteString(FName);
end;

procedure TNewObject.DefineProperties(Filer:TFiler);
begin
inherited;
Filer.DefineProperty('bizname',ReadName,WriteName,FName<>'');
end;


I have a TObjectList, which I am trying to write to disk. Although I end up with a file (54 bytes), when I change the FNAME property value to something really long, the size of the file never changes, and I get nil when I try to read it. I am at a loss as to what is wrong. Sorry for the long code snippet. it is easy to understand what is going on, just I can't figure out why it's not doing what I want.

type
  { Declare a new object type. }
  TNewObject = class(TComponent)
  private
    FName: String;
  public
    property BizName: String read FName write FName;
    constructor Create(const AName: String);
    destructor Destroy(); override;
  end;

Declare a Global var for my TObjectList

var
  Form1: TForm1;
  List: TObjectList<TNewObject>;

Declare my constructors and destructors..

constructor TNewObject.Create(const AName: String);
begin
  FName := AName;            
end;

destructor TNewObject.Destroy;
begin      
  inherited;
end;

Now add a button to create my objects...

procedure TForm1.CreateButtonClick(Sender: TObject);  
    var     
      Obj: TNewObject;
    begin
      { Create a new List. }
      { The OwnsObjects property is set by default to true -- the list will free the owned objects automatically. }
      List := TObjectList<TNewObject>.Create();

      { Add some items to the List. }
      List.Add(TNewObject.Create('One'));
      List.Add(TNewObject.Create('Two'));

      { Add a new item, but keep the reference. }
      Obj := TNewObject.Create('Three');
      List.Add(Obj);
end;

Now add a SAVE Button

procedure TForm1.SaveButtonClick(Sender: TObject);
var
  i: Integer;
  fs: TfileStream;
begin
  if SaveDialog1.Execute then
  begin
    fs := TfileStream.Create(SaveDialog1.FileName, fmCreate);
    try
      for i := 0 to List.Count - 1 do
      begin

        ShowMessage(List[i].BizName);
        fs.WriteComponent(TNewObject(List[i]));            
      end;
    finally
      fs.Free;
    end;
  end;
end;

CAVEATS: I know that only PUBLIC properties will be saved... which should be BIZNAME. The 3 entries do show up in the SHOWMESSAGE when it is being saved....

I did remember my Class Registration.

Initialization
RegisterClass(TNewObject); 

For completeness sake, here is my Load Routine as well...

procedure TForm1.LoadButtonClick(Sender: TObject);
var
  i: Integer;
  fs: TfileStream;
  vRecord: TNewObject;
begin
  if OpenDialog1.Execute then
  begin
    List.Clear; // clear list
    fs := TfileStream.Create(OpenDialog1.FileName, fmopenRead);
    try

      while fs.Position < fs.size do
      begin
        vRecord := TNewObject(fs.ReadComponent(nil));
        ShowMessage(vRecord.FName);           
        List.Add(vRecord);
      end;
    finally
      fs.Free;
    end;
    ShowMessage(IntToStr(List.Count));
  end;
end;

Thank you for your help.

解决方案

Component streaming system only streams published properties, you need to publish 'BizName'.

Alternatively you can override DefineProperties to decide what else to stream.

type
  TNewObject = class(TComponent)
  private
    FName: String;
    procedure ReadName(Reader: TReader);
    procedure WriteName(Writer: TWriter);
  protected
    procedure DefineProperties(Filer: TFiler); override;
  public
    property BizName: String read FName write FName;
    ...

procedure TNewObject.ReadName(Reader: TReader);
begin
  FName := Reader.ReadString;
end;

procedure TNewObject.WriteName(Writer: TWriter);
begin
  Writer.WriteString(FName);
end;

procedure TNewObject.DefineProperties(Filer: TFiler);
begin
  inherited;
  Filer.DefineProperty('bizname', ReadName, WriteName, FName <> '');
end;

这篇关于Delphi - 无法保存/加载TObjectList到FileStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆