【问题标题】:delphi Save and Load dynamic arraydelphi 保存和加载动态数组
【发布时间】:2012-01-27 10:45:09
【问题描述】:

请有人帮我从流中保存和加载它的动态数组

const
      iGlobHolderCount = 100;

    type
      TFiLeSpec = record
        iSize: Integer;
      end;

      TFileSpecLst = array of TFiLeSpec;

      TFiLeSpecList = record
        iMin: Integer;
        iMax: Integer;
        iCount: Integer;
        FileSpecLst: TFileSpecLst;
      end;


var
FFileSpec: array of TFiLeSpec;

FFileSpecList: array [1 .. iGlobHolderCount] of TFiLeSpecList;

【问题讨论】:

  • 你尝试了什么?现在看起来像是一个Show me teh codez 问题。
  • 您是否尝试过我对您的其他问题 (stackoverflow.com/questions/8819885/…) 的回答中显示的技术,或者您的其他问题的第一条评论中建议的变体? (stackoverflow.com/questions/3820996/…)。您应该尝试自己解决这个问题并发布失败的代码。没有它,这真的是一个"Show me teh codez" 的问题。投票结束时“过于本地化”,因为这只会帮助你,永远不会帮助其他人。
  • @Cosmin Prund ,不,这不是给我看 codez ,但老实说,我不知道如何从 Stream 保存和加载动态数组。
  • 帮我一个忙。阅读我链接的两个问题的答案,并尝试自己解决这个问题。如果您尝试失败,请在不少于 60 分钟内回复评论,我会给您代码。提示:第二个问题包含保存动态数组的代码。
  • stackoverflow.com/questions/3820996/… 这不是我的问题,但我会根据建议尝试。谢谢

标签: arrays delphi


【解决方案1】:

先写入数组的长度,然后写入数组数据:

type
  TItem = Integer;
  TItemArray = array of TItem;

var
  Stream: TStream;
  Arr: TItemArray;
  L: LongWord;

begin
  Arr:= TItemArray.Create(1, 2, 3);
// To save
  Stream:= TFileStream.Create('C:\Temp\test.bin', fmCreate);
  L:= Length(Arr);
  Stream.WriteBuffer(L, SizeOf(L));
  Stream.WriteBuffer(Pointer(Arr)^, L * SizeOf(TItem));
  Stream.Free;
// To load
  Stream:= TFileStream.Create('C:\Temp\test.bin', fmOpenRead);
  Stream.ReadBuffer(L, SizeOf(L));
  SetLength(Arr, L);
  Stream.ReadBuffer(Pointer(Arr)^, L * SizeOf(TItem));
  Stream.Free;
end;

【讨论】:

    【解决方案2】:

    从 Delphi 5 到 XE2 的另一种解决方案是使用我们核心 OpenSource 单元的一些功能。

    其实它实现了:

    • 一些用于处理记录类型的低级 RTTI 函数:RecordEquals、RecordSave、RecordSaveLength、RecordLoad;
    • 一个专用的 TDynArray 对象,它是任何动态数组的包装器,能够在任何动态数组周围公开类似 TList 的方法,甚至包含记录、字符串或其他动态数组。它能够序列化任何动态数组。
    • 序列化使用优化的二进制格式,能够将任何记录或动态数组作为 RawByteString 保存和加载。

    你可以编码,例如

    var
      FFileSpec: array of TFiLeSpec;
      TFileSpecList = array of TFiLeSpecList;
      FFileSpecList: TFileSpecList;
    
    var FSL: TDynArray;
        Bin: RawByteString;
    begin
      FSL.Init(TypeInfo(TFiLeSpecList),FFileSpecList);
      // ... then you use FFileSpecList[] as usual
      // ... or use some methods of FSL:
      if FSL.Count>0 then
        FSL.Delete(0);
      FSL.Add(FFileSpec);
      FSL.Clear;
      // then you can serialize the content to binary
      Bin := FSL.SaveTo;
      // use FSL.LoadFrom(Bin) to read the whole array content back
      // or you can use a TStream 
      FSL.SaveToStream(aStream); 
      FSL.Clear;
      aStream.Position := 0;
      FSL.LoadFrom(aStream);
      // you do not need to release nor Free FSL: this is a wrapper around FFileSpecList
    end;
    

    请注意,我已将您的 TFileSpecList 替换为动态数组,但您可以在记录内使用固定数组来提供额外的 RTTI - 然后使用 RecordLoad / RecordSave 函数。它将使用 RTTI(即使使用 Delphi 5)保存内部动态数组内容,处理任何 string 或其中的嵌套数组。

    我们的 mORMot 框架使用它(例如,用于将动态数组 serialization 放入 DB 中),但它不是其中的一部分:只需要一个单元,也不需要 SQLite3 或整个 ORM 类。

    this page for additional information

    【讨论】:

    猜你喜欢
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 2011-10-03
    相关资源
    最近更新 更多