Results 1 to 4 of 4

Thread: save/load a dynamic array

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    first of all use code tags when you're inserting large parts of the code. the way it is here will strip people of any desire to help you.
    there is a lot of commented code which is unnecesary here and I assume it confuses you as well.
    for example:
    you read the number of records here:
    FS.ReadBuffer(FileSize, SizeOf(FileSize));

    but you never write it.

    so my advice is clean you code, work through it step by step and you will surely fix all your problems.
    Last edited by Dan; 06-11-2010 at 04:27 AM.

  2. #2
    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

  3. #3
    Like Dan pointed out, the code should only be missing this from the saving part:

    Code:
    FS.WriteBuffer(integer(REC_COUNT), SizeOf(integer));
    But if the record count is always same constant its not even necessary to read FileSize if it is always REC_COUNT.

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
  •