简体   繁体   English

delphi保存并加载动态数组

[英]delphi Save and Load dynamic array

please can someone help me in saving and loading its Dynamic array from a Stream 请有人帮我保存并从Stream加载其动态数组

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;

Another solution, working from Delphi 5 up to XE2, is to use some features of one our core OpenSource unit. 从Delphi 5到XE2的另一个解决方案是使用我们的核心OpenSource单元的一些功能。

In fact, it implements: 实际上,它实现了:

  • some low-level RTTI functions for handling record types: RecordEquals, RecordSave, RecordSaveLength, RecordLoad; 一些用于处理记录类型的低级RTTI函数:RecordEquals,RecordSave,RecordSaveLength,RecordLoad;
  • a dedicated TDynArray object, which is a wrapper around any dynamic array, able to expose TList-like methods around any dynamic array, even containing records, strings, or other dynamic arrays. 一个专用的TDynArray对象,它是任何动态数组的包装器,能够在任何动态数组周围显示类似TList的方法,甚至包含记录,字符串或其他动态数组。 It's able to serialize any dynamic array. 它能够序列化任何动态数组。
  • Serialization uses an optimized binary format, and is able to save and load any record or dynamic array as RawByteString. 序列化使用优化的二进制格式,并能够将任何记录或动态数组保存并加载为RawByteString。

You can code, eg 你可以编码,例如

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;

Note that I've replace your TFileSpecList by a dynamic array, but you may use a fixed array instead, inside a record to provide additional RTTI - then use RecordLoad / RecordSave functions. 请注意,我已用动态数组替换TFileSpecList ,但您可以使用固定数组,在记录中提供额外的RTTI - 然后使用RecordLoad / RecordSave函数。 It will save the internal dynamic array content using RTTI (even with Delphi 5), handling any string or nested array within. 它将使用RTTI(即使使用Delphi 5)保存内部动态数组内容,处理其中的任何string或嵌套数组。

It's used by our mORMot framework (eg for serialization of dynamic arrays into the DB), but it's not part of it: just one unit, nor SQLite3 nor the whole ORM classes are needed. 它由我们的mORMot框架使用(例如,用于动态数组序列化到DB中),但它不是它的一部分:只需要一个单元,SQLite3,也不需要整个ORM类。

See this page for additional information . 有关其他信息,请参阅此页面

Write first the length of an array, and next the array data: 首先写入数组的长度,然后写入数组数据:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM