0

I have problems when I try to write an array of pointers to a file:

type

  PInt = ^Int64;

  TArray = Array[ 0..5 ] of PInt;

procedure Save( AFileHandle: THandle; AArray: TArray );
begin
  FileWrite( AFileHandle, AArray[ 0 ]^, Length( AArray ) * SizeOf( PInt ) );
end;

procedure Load( AFileHandle: THandle; AArray: TArray );
var
  I: Int32;
begin
  for I := 0 to Length( AArray ) - 1 do
    AArray[ I ] := AllocMem( SizeOf( PInt ) );
  FileRead( AFileHandle, AArray[ 0 ]^, Length( AArray ) * SizeOf( PInt ) );
end;

Can avoid writing every single item by writing everything at once?

Thanks.

6
  • 1
    if you have only pointers to <anytype> in the array there is no other way i think. Or copy it first to a Array of int64 and write that. Commented Jul 25, 2017 at 20:15
  • What problem are you having? Commented Jul 25, 2017 at 20:15
  • 2
    Why on earth are you writing pointers to a file? They are very likely not valid anymore when you read them back. Write the Int64s instead. Commented Jul 25, 2017 at 20:20
  • I don't try write pointers! But value of pointers. I have simplified, indeed I have an array of record pointers. For performance issues I wanted to write all at once. Writing first in a stream or in a record array is lost a lot. Commented Jul 25, 2017 at 20:23
  • 1
    Thats like eggs, if you want to put them in a box you have to collect them first. There i no other way Commented Jul 25, 2017 at 20:34

2 Answers 2

5

Your question is slightly confusing. I can't imagine that you are trying to actually write the pointers themselves (they would very likely be invalid when you read them back), just the Int64s they point to. If that is the case, you are not doing it right.

If the array really contains pointers, then you can't write the items in one go. The pointers are in one contiguous block, but not necessarily the items they point to. You will have to write them one by one:

procedure Save(AFileHandle: THandle; AArray: TArray);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    FileWrite(AFileHandle, AArray[I]^, SizeOf(Int64));
end;

or, alternatively:

procedure Save(AFileHandle: THandle; AArray: TArray);
var
  P: PInt;
begin
  for P in AAray do
    FileWrite(AFileHandle, P^, SizeOf(P^));
end;

And reading back:

procedure Load(AFileHandle: THandle; var AArray: TArray);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
  begin
    New(AArray[I]);
    FileRead(AFileHandle, AArray[I]^, SizeOf(Int64));
  end;
end;

You read and write SizeOf(PInt), but that would write the size of a pointer, not the size of an Int64.


As Sertac writes, you could write them in one go (and read them too), thus avoiding having to call FileWrite or FileRead repeatedly, if you copy the Int64s to a contiguous block first (assuming that each call to file I/O is much slower than copying the values to a single array):

type
  PSaveArray = ^TSaveArray;
  TSaveArray = array[0..5] of Int64;

procedure Save(AFileHandle: THandle; AArray: TArray);
var
  Save: TSaveArray;
  I: Integer;
begin
  for I := 0 to 5 do
    Save[I] := AArray[I]^;
  FileWrite(AFileHandle, Save, SizeOf(Save));
end;

Reading back would be similar:

procedure Load(AFileHandle: THandle; var AArray: TArray);
var
  Items: PSaveArray;
  I: Integer;
begin
  New(Items);
  FileRead(AFileHandle, Items^, Sizeof(Items^));
  for I := Low(Items) to High(Items) do
    AArray[I] := Addr(Items^[I]);
end;
Sign up to request clarification or add additional context in comments.

3 Comments

If the question is as you've understood, you can populate an array first and then write it once. It will lift the burden from file I/O.
Yes, that would be a possibility. More work, but probably faster. I'll add that.
Ok, was enough "then you can't write the items in one go". Thanks all.
0

Since the values are scattered over the heap, you can use Scatter-Gather IO to read/write them: https://learn.microsoft.com/en-us/windows/win32/fileio/reading-from-or-writing-to-files-using-a-scatter-gather-scheme

However, it's probably easier to do "gather-before-write" yourself rather than deal with those functions. Consider also that these function are OS-specific, so this approach is not cross-platform.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.