TStringList可以把字符串加进去,然后saveAsFile, 用的时候,可以loadFromFile()来从文件中还原对象,我想知道,有没有哪个类可以把对象加进去,然后可以saveAsFile,然后
用的时候,可以类似loadFromFile来还原的? 本来TStringList来addObject方法,但是我发现addObject()加对象进去后,再saveAsFile,文件内容是不包括对象的字节码的。请问有人遇到过这个问题吗?或者怎样解决这个问题。希望回答具体点,谢谢了。

解决方案 »

  1.   

    我是要把整个对象的内存中的二进制存到文本中,然后再从文本中还原成对象。Java中就有ObjectInputStream是这个功能的。不知delphi中有没有。
      

  2.   

    是      我再具体说说我为什么要这样做,因为我现在要把一些设计好的多个图片的字节码加密后存为一个文件,这个文件是可以作为图片库传给客户的,然后客户就用程序打开这个文件来看到里面的素材图片。原来我用access来存,但由于每张图片是几十M那么大的,所以效率很低,Access在各种数据库中本来效率就是最低的,但是它的好处是可以作为一个"升级的图片库"发给用户。我现在是设想如果一个类,可以一个key对应一个value的形式来存放数据,并且有方法可以把整个对象存为文件,或者从文件还原对象,就最省事了,key就作为一个索引,value上就存图片的字节码,还要有insert,delete,append等方法,这样无论存或取都很方便。后来发现了TStringList这个类,大部分都符合我的要求,就是addObject()后,不能把对象存在文本中。现在发现TValueListEditor也是key->value这样的结构的,但是我看过帮助,这个类没有saveAsStream()或loadFromStream()之类的方法的。   请教一下有丰富delphi项目经验的高手,我这个需求应怎么解决。分不够再加,谢谢了。顶者有分。
      

  3.   

    delphi应该没有,TStringList的AddObject中的参数为 TObject类型,而 TObject类型其实是类的指针,且Tobject中也有指针类型(如 ClassParent),所以,AddObject实际上只是将指针加入了,如果你要真正将TObject内容加入,就必须将TObject所指向的内容加入(如47522341所说,名称之类的关键属性),并将它内容中的指针指向的内容加入(如果有的话,有点像链表内容)
    JAVA相对简单,它没有指针,它的类是静态的(如C的静态类),所以它的内容是可直接取到的
      

  4.   


        TMemoryStream.WriteComponent
        TMemoryStream.SaveToFile
    可以把一TComponent存成二进制文件,用readComponent读取
      

  5.   

    首先, 这个问题你必须自己写代码, 比较好的方法是你构造自己的列表类, 这样类型安全, 如类声明的关键部分可以如下:type
      TGraphicItem = class
      private
        FKey: String;
        FGraphic: TGraphic;
      public
        property Key: String read FKey write FKey;
        property Graphic: TGraphic read FGraphic write FGraphic;
        procedure ReadFromStream(AStream: TStream);
        procedure WriteToStream(AStream: TStream);
      end;  TGraphicList = class(TObjectList)
      public
        property Items[Index: Integer]: TGraphicItem read GetItem write SetItem; default;
        procedure LoadFromStream(AStream: TStream);
        procedure SaveToStream(AStream: TStream);
        procedure LoadFromFile(const AFileName: String);
        procedure SaveToFile(const AFileName: String);
      end;// LoadFromFile 实现如下所示
    // 注意, 此处使用的是TFileStream, 不要使用TMemoryStream, 因为使用TMemoryStream
    // 会浪费更多的内存空间
    procedure TGraphicList.LoadFromFile(const AFileName: String);
    var
      tmpStream: TFileStream;
    begin
      tmpStream := TFileStream.Create(AFileName, fmOpenRead);
      try
        LoadFromStream(tmpStream);
      finally
        tmpStream.Free;
      end;
    end;// SaveToFile 的实现方法如下
    procedure TGraphicList.SaveToFile(const AFileName: String);
    var
      tmpStream: TFileStream;
    begin
      tmpStream := TFileStream.Create(AFileName, fmCreate);
      try
        SaveToStream(tmpStream);
      finally
        tmpStream.Free;
      end;
    end;// SaveToStream 实现如下
    procedure TGraphicList.SaveToStream(AStream: TStream);
    var 
      i: Integer;
      tmpCount: Integer;
    begin
      tmpCount := Count;
      AStream.WriteBuffer(tmpCount, sizeof(tmpCount));
      for i := 0 to tmpCount - 1 do
        Items[i].WriteToStream(AStream);
    end;// LoadFromStream 实现如下
    procedure TGraphicList.LoadFromStream(AStream: TStream);
    var
      tmpCount: Integer;
      i: Integer;
      tmpItem: TGraphicItem;
    begin
      Clear;  // 注意此处如果OwnsObjects属性为True时, 其自动释放了列表中的所有对象
          // 如果OwnsObjects为False时, 则需要则需要在此句之前增加释放列表中的所有对象的代码
      AStream.ReadBuffer(tmpCount, sizeof(tmpCount));
      for i := tmpCount - 1 downto 0 do
      begin
        tmpItem := TGraphicItem.Create;
        try
          tmpItem.ReadFromStream(AStream);
          Add(tmpItem);
        except
          tmpItem.Free;
          raise; 
        end;
      end;
    end;先写到这儿, 下面继续
    对于图像的保存, 可以保存图象的二进制数据, 因为这样其数据量较小
    对于TGraphicItem, 必须保存Key, 二进制数据, 图像类型的标识(此处, 我使用类名)
    对于字符串的保存, 先保存长度, 再保存内容
    对于二进制数据的保存, 也先保存其长度, 再保存内容字符串的写入和读取函数如下
    procedure WriteStringToStream(AStream: TStream; const AValue: String);
    var
      iLen: Integer;
    begin
      iLen := length(AValue);
      AStream.WriteBuffer(iLen, sizeof(iLen));
      if iLen > 0 then
        AStream.WriteBuffer(AValue[1], iLen);
    end;function ReadStringFromStream(AStream: TStream): String;
    var
      iLen: Integer;
    begin
      AStream.ReadBuffer(iLen, sizeof(iLen));
      SetLength(Result, iLen);
      if iLen > 0 then
        AStream.ReadBuffer(Result[1], iLen);
    end;二进制数据的写入的读取函数如下
    procedure WriteStreamToStream(AStream: TStream; sub: TMemoryStream);
    var
      iLen: Integer;
    begin
      iLen := sub.Size;
      AStream.WriteBuffer(iLen, sizeof(iLen));
      if iLen > 0 then
        AStream.WriteBuffer(sub.Memory^, iLen);
    end;procedure ReadStreamFromStream(AStream: TStream; sub: TMemoryStream);
    var
      iLen: Integer;
    begin
      AStream.ReadBuffer(iLen, sizeof(iLen));
      sub.SetSize(iLen);
      if iLen > 0 then
        AStream.ReadBuffer(sub.Memory^, iLen);
    end;对于各项的读取和写入, 实现如下
    procedure TGraphicItem.WriteToStream(AStream: TStream);
    var
      sub: TMemoryStream;
    begin
      WriteStringToStream(AStream, FKey);
      WriteStringToStream(AStream, FGraphic.ClassName);
      sub := TMemoryStream.Create;
      try
        FGraphic.SaveToStream(sub);
        WriteStreamToStream(AStream, sub);
      finally
        sub.free;
      end;
    end;procedure TGraphicItem.WriteToStream(AStream: TStream);
    var
      sub: TMemoryStream;
      tmpClassName: String;
      tmpClass: TGraphicClass;
    begin
      FKey := ReadStringFromStream(AStream);
      tmpClassName := ReadStringFromStream(AStream);
      tmpClass := TGraphicClass(GetClass(tmpClassName));
      if tmpClass = nil then
        raise Exception.Create('graphic type not support'); // 此处最好用你自己声明的异常  if Assigned(FGraphic) then
        FreeAndNil(FGraphic);  FGraphic := tmpClass.Create;
      sub := TMemoryStream.Create;
      try
        ReadStreamFromStream(AStream, sub);
        sub.Position := 0;
        FGraphic.LoadFromStream(sub);
      finally
        sub.Free;
      end;
    end;至此OK, 你所需要的关键部分都已经给出来了
      

  6.   

    WriteComponentResFile最大的问题就是局限在只能用于从TComponent继承下来的对象,要能象c#那样可以序列化任意类,那这个问题就很好解决了.我也曾经问过delphi里有没这样的机制,答案貌似是没有 -_-|
      

  7.   

    将你的图片数据作为资源保存在dll中。前提是用户不能添加数据。
      

  8.   

    谢谢hangzhou_hammer(ㄛ鎯頭[鉄的]) 
      

  9.   

    TPersistent被设计用来使对象可以流化(序列化),而不是从TComponent开始。如果想要使用这一机制,需要从TPersitent派生。否则得自己创建机制。不过虽然有了TPersistent,在读取对象内容时还需要知道要创建什么类的对象。--
    http://www.agui.googlepages.com
    mailto: agui.cn(a)gmail.com