delphi保存并加载动态数组

时间:2012-01-27 10:45:09

标签: arrays delphi

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

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;

2 个答案:

答案 0 :(得分:5)

从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进入数据库),但它不是它的一部分:只需要一个单元,也不需要SQLite3,也不需要整个ORM类。

请参阅this page for additional information

答案 1 :(得分:4)

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

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;