6

Hi I have defined some records in my project which may be consisted of other records and also dynamic arrays of normal data types and other records , it is n example of a record type

  Type1=record
    x:integer;
  end;
  Type2=record
    Y:array of X;
    str:string;
  end;

When I tried to save one of variables of these records type to file with blockwrite function like this :

var
  Temp1:Type2;
  begin
    setlength(temp1.y,100);
    blockwrite(MyFile,Temp1,sizeOf(Temp1);

it just wrote as much as the size of pure record is ,but temp1 has a dynmic arrays which is resized , Could someone please tell me how I can write a complex record to a file , I mean something like what is used in VB6 . Thanks

DrSobhani
  • 129
  • 7
  • 3
    See also: [Delphi 2010: How to save a whole record to a file?](http://stackoverflow.com/questions/3820996). – Sertac Akyuz Dec 26 '10 at 10:42
  • A new [OpenSource unit and classes](http://blog.synopse.info/post/2011/03/12/TDynArray-and-Record-compare/load/save-using-fast-RTTI) worth considering for serializing records or dynamic arrays (with a lot more features than serialization) - working for Delphi 5 up to XE2. – Arnaud Bouchez Nov 08 '11 at 07:27

2 Answers2

7

You can use https://github.com/KrystianBigaj/kblib (works with any dynamic records, also records that contains other records, etc.). Tested on Delphi 2006/2009/XE (it doesn't use extended RTTI introduced in D2010). No need to write save/load code manually (just one line to save/load any dynamic type - strings, records, dynamic arrays).

In your example it would be sth. like this:

TKBDynamic.WriteTo(lStream, lType2, TypeInfo(Type2));

To load it back:

TKBDynamic.ReadFrom(lStream, lType2, TypeInfo(Type2));

If anyone is interested how to deal with 'record versions', just post new issue and then I'll write some examples.

Similar questsion:

Krystian Bigaj
  • 1,295
  • 8
  • 14
  • +1 This works very well. Code could be made compatible with upcoming 64 bit compiler, by using NativeUInt instead of cardinal for pointer arithmetic. – Arnaud Bouchez Dec 26 '10 at 13:23
  • When Delphi64 will be release, I'll upgrade code. Now I cannot test it in Delphi x64 at all, so making future-proof code without testing could bring bugs (or not work properly in x64). I know that it's simple pointer-math, but still... :) – Krystian Bigaj Dec 26 '10 at 13:29
  • Also probably with D64 structure for example of string header will change (I think that content of string should be aligned to 8 bytes, now in >=D2009, it's 12 bytes, so in D64 it should be 16 bytes) - just my guess. Such a change won't break binary structure of saved TKBDynamic, but code will need to be upgraded in kblib. So I'll wait with changes till release. – Krystian Bigaj Dec 26 '10 at 13:37
  • @kibab that's a nice looking library, too bad my versioning requirements mean I could never use it or indeed the RTTI techniques contained within. – David Heffernan Dec 26 '10 at 14:34
  • @kibab: you can be 100% sure that NativeUInt is to be used for pointer arithmetic with the 64 bit compiler. It was also said that the string header won't change with the upcoming version (there is no reason to - and in all cases, using SetString is always safe). Default aligment can change in future version, but it will be handled by the current code, because it's coded in the RTTI (in the offsets values). If you are using records for serialization, I'd recommend using a packed record, because it will use less storage space, and it will be cross-compiler ready, whatever the default aligment is – Arnaud Bouchez Dec 26 '10 at 17:17
  • @Marco van de Voort - I've reverted that D2010+ addition, because here I'm NOT using extended RTTI introduced in D2010. This code was mainly developed and tested under D2009 (but I've also made a quick test in D2006 and XE). It should work also fine under D7. – Krystian Bigaj Dec 26 '10 at 18:50
  • What info does it iterate then? The intialization information? That is afaik not guaranteed cross-version (or compiler) compatible. – Marco van de Voort Dec 27 '10 at 19:04
  • I'm using RTTI for records/dyn-arrays that are used for Initialize/Finalize (see System.pas) code is also similar :), so yes it's probably that initialization information you said. And about compatibility - since D2010+ I could use that extended RTTI which would save/load in same binary code that is used for – Krystian Bigaj Dec 27 '10 at 19:52
0

This won't work. You will need to manually write (streaming) code to write every field.

Have a look at published fields/properties in classes, since together with arrays of variants, this used to be the only way to stream data using generic code.

However since D2010 the RTTI was expanded, but I don't know the exact details of that yet.

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89
  • Indeed. My codebase has a large section devoted to doing just this. The string persistence code writes the length followed by the content, for example. Depending on how you see your code developing it may be worth building in compatibility features to the file format. I expect that there are 3rd party components to do this stuff but I've personally always done it myself. – David Heffernan Dec 26 '10 at 10:30
  • Fileformat compatibility is why I mostly have manually streamed code too. I have to confess though that mine aren't terribly large or complex – Marco van de Voort Dec 26 '10 at 10:42