I have such file:

file of record
  Str: string[250];
  RecType: Cardinal;
end;

but after some time using of this file my customer found, that Str never be bigger than 100 chars and also he need additional fields.

In new version we have such file:

file of packed record
  Str: string[200];
  Reserved: array[1..47] of Byte;
  NewFiled: Cardinal;
  RecType: Cardinal;
end;

This record have the same size, in previous record between Str and RecType was one unused byte when aligned to 8 bytes.

Question: what happened, when this new file will be readed from old code? He need backward compatability.

Old code reading sample:

var
  FS: TFileStream;
  Rec: record
         Str: string[250];
         RecType: Cardinal;
       end;
...
// reading record by record from file:
FS.Read(Rec, SizeOf(Rec));
有帮助吗?

解决方案

The old school pascal string use the first byte of the string (index 0) to store the length of the string.

Let's look at the memory of this record:

byte    0  1  2  3  4  5  6  7  8  9 10 11  12  13 ........ 243..246 247..250
value  10 65 66 67 68 69 70 71 72 73 74  0 200 130          NewField RecType

From byte 11 to 242, the memory can contain garbage, it is simply ignored by the program (never shown) as this takes the value 10 at the byte 0 as the length of the string, so the string becomes 'ABCDEFGHIJ'

This ensures the old program reading a file created with the most recent version will never see garbage at the end of the strings, since the view of that strings will be limited to the actual size of the string and that memory positions are just ignored.

You have to double check if the old program does not change the values stored in case it writes the records back to the file. I think it is also safe, but I'm just not sure and have no Delphi at hand to test.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top