Results 1 to 4 of 4

Thread: save/load a dynamic array

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #3
    Saving/Loading a dynamic array on a stream pretty much amounts to:

    1) Writing the array elements count onto the stream.
    2) Looping through the array and writing out each element's contents, fully dereferenced, to the stream. That means the element and any part of its content has to contain no non-dereferenced pointers. Stream I/O functions expect the variables they are passed to not be or contain pointers; otherwise, you'll just store the pointer values, rather than the data in what the pointers point to.

    More or less, you're handing an untyped bucket of data to the stream write function, and it doesn't know or care what the data actually is inside the bucket. Likewise, when you read data from a stream, you pass an empty bucket and how much untyped data you want to fill it with.

    Also, the reads have to exactly mirror/balance the writes, or Things Go Bad (tm).

    With the simple record structure you are using (all well-defined static scalar types), you can just write/read it straight up. However, if you put a string or other dynamic type into that record later, you'll have to add code in the element write function to "descend into" those dynamic types and read/write them appropriately dereferenced.

    In terms of code:

    Code:
    Type
      TMyDataRecord = Record
        X,Y,Index : Integer;
        End;
    
    Var
      AMyDataArray = Array Of TMyDataRecord;
    
    Procedure WriteMyData;
    
      Var
        FS : TFileStream;
        I,iCount : Integer;
    
      Begin
      FS := TFileStream.Create(ExtractFilePath(Paramstr(0)) + 'test.dat', fmOpenWrite);
      iSize = Length(AMyDataArray);
      FS.WriteBuffer(iSize,SizeOf(iSize));
      For I := 0 To iSize - 1 Do
        FS.WriteBuffer(AMyDataArray[I],SizeOf(TMyDataRecord));
      FS.Free;
      End;
    
    Procedure ReadMyData;
    
      Var
        FS : TFileStream;
        I,iCount : Integer;
        RData : TMyDataRecord;
    
      Begin
      FS := TFileStream.Create(ExtractFilePath(Paramstr(0)) + 'test.dat', fmOpenRead);
      FS.ReadBuffer(iSize,SizeOf(iSize));
      SetLength(AMyDataArray,iSize);
      For I := 0 To iSize - 1 Do
        Begin
        FS.ReadBuffer(RData,SizeOf(TMyDataRecord));
        AMyDataArray[I] := RData;
        End;
      FS.Free;
      End;
    It has no error handling, but that's basically what you have to do.
    Last edited by Murmandamus; 06-11-2010 at 10:43 PM. Reason: Typos

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •