Recent

Author Topic: Hardcopy of a record to hard disk  (Read 4546 times)

Tommi

  • Full Member
  • ***
  • Posts: 213
Hardcopy of a record to hard disk
« on: April 22, 2014, 10:02:07 pm »
Hello,
I would like to save a complex record (with multidimensional arrays) to hard disk.
Yes, I know that I could save it field by field but it is not comfortable because every time I update my  code I also have to change save/read routines.

I would like to do a raw copy of ram to hard disk. I think that it should be possible but I don't know how because sizeOf() doesn't return the value of my record.

Thank you

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Hardcopy of a record to hard disk
« Reply #1 on: April 22, 2014, 10:13:20 pm »
You can't do a raw copy of the block of memory because if sizeof doesn't return what you expect, you are probably using dynamic types which are not contagious in memory.

Tommi

  • Full Member
  • ***
  • Posts: 213
Re: Hardcopy of a record to hard disk
« Reply #2 on: April 22, 2014, 10:19:11 pm »
OK,
so the only way is to manually save field by field ?

Tommi

  • Full Member
  • ***
  • Posts: 213
Re: Hardcopy of a record to hard disk
« Reply #3 on: April 22, 2014, 10:31:18 pm »
If data are not contiguous is safe do this to save a dynamic array ?
Code: [Select]
wi is an array of array of double.

      iCount:=length(wi); 
      strm.Write(iCount,sizeOf(integer));
      for a := 0 to length(wi)-1 do
      begin
           iCount:=length(wi[a]);
           strm.Write(iCount,sizeOf(integer));
           strm.Write(wi[a],sizeOf(double)*iCount);
      end;   
 

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Hardcopy of a record to hard disk
« Reply #4 on: April 23, 2014, 12:10:15 am »
How can you guarantee your dynamic array is always symmetrical?
I think you would have to write something like this
Code: [Select]
var
  outerLength, outerIndex, innerLength: integer;
begin
  outerLength:=Length(anArray);
  aStream.Write(outerLength, sizeOf(integer));
  for outerIndex:= 0 to outerLength-1 do
  begin
    innerLength:=Length(anArray[outerIndex]);
    aStream.Write(innerLength, SizeOf(integer));
    aStream.Write(anArray[outerIndex], SizeOf(double)*innerLength);
  end;
end;     

Best way is to try it out and see whether your code reliably yields the results you expect.



Tommi

  • Full Member
  • ***
  • Posts: 213
Re: Hardcopy of a record to hard disk
« Reply #5 on: April 23, 2014, 11:13:07 pm »
Yes, I have done as you suggest. If the array is dynamic I think it is impossible to be sure that the data aren't fragmented. So the only way is to save data by data.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Hardcopy of a record to hard disk
« Reply #6 on: April 24, 2014, 11:20:05 am »
Almost, corrected code:

Code: [Select]
      iCount:=length(wi); 
      strm.Write(iCount,sizeOf(integer));
      for a := 0 to length(wi)-1 do
      begin
           iCount:=length(wi[a]);
           strm.Write(iCount,sizeOf(integer));
           if icount>0  then // added
             strm.Write(wi[a][0],sizeOf(double)*iCount);  // [0] added.
      end;   
 

Tommi

  • Full Member
  • ***
  • Posts: 213
Re: Hardcopy of a record to hard disk
« Reply #7 on: April 24, 2014, 12:28:36 pm »
Yes but my doubt is:
lets suppose that I have two dynamic arrays of bytes, wi and wo. If I do:

Code: [Select]
setLength(wi,1);
setLength(wi[0],3);
wi[0,0]:=1;
wi[0,1]:=2;
wi[0,2]:=3;
now in memory I have a stream like this:
(I know that there are control bytes, but for semplicity)
Code: [Select]
0x01 0x02 0x03
now if I do:
Code: [Select]
setLength(wo,1);
setLength(wo[0],3);
wo[0,0]:=40;
wo[0,1]:=50;
wo[0,2]:=60;
now my stream is:
Code: [Select]
0x01 0x02 0x03 0x40 0x50 0x60
now I decide to make wi bigger:
Code: [Select]
setLength(wi[0],6);
wi[0,3]:=4;
wi[0,4]:=5;
wi[0,5]:=6;
Now in memory I should find something like this:
Code: [Select]
0x01 0x02 0x03 0x40 0x50 0x60 0x04 0x05 0x06
Now, if I do:
Code: [Select]
      iCount:=length(wi); 
      strm.Write(iCount,sizeOf(integer));
      for a := 0 to length(wi)-1 do
      begin
           iCount:=length(wi[a]);
           strm.Write(iCount,sizeOf(integer));
           if icount>0  then // added
             strm.Write(wi[a][0],sizeOf(double)*iCount);  // [0] added.
      end;   

Am I sure that in the stream I will find 0x01 0x02 0x03 0x04 0x05 0x06 and not 0x01 0x02 0x03 0x40 0x50 0x60 ?
Unfortunately it is diffuclt to make tests about it because 99% of cases it could go well and 1% go wrong but it is important to know.

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Hardcopy of a record to hard disk
« Reply #8 on: April 24, 2014, 12:56:25 pm »
Setlength() doesn't do anything if the size doesn't change. If it does, it allocates a new memory block and copies existing values over (the new memoryblock could start from entirely different pointer address, not necessarily continuous). When setting 2-dimensional array, you can do Setlength(myArray, 10, 20) to make a 10x20 grid. But reallocating 2-dimensional array might not exactly copy the existing values over, at least you shouldn't trust that it would.

Your stream after second code would be
Code: [Select]
0x40 0x50 0x60You are overwriting the 1 2 3 in same memory address.

Quote
Am I sure that in the stream I will find 0x01 0x02 0x03 0x04 0x05 0x06 and not 0x01 0x02 0x03 0x40 0x50 0x60 ?
Unfortunately it is diffuclt to make tests about it because 99% of cases it could go well and 1% go wrong but it is important to know.
No you aren't sure of that. But marcov's code does it differently and works 100% of times.
« Last Edit: April 24, 2014, 01:07:33 pm by User137 »

 

TinyPortal © 2005-2018