【问题标题】:Upgrade for file of records and backward compatability升级记录文件和向后兼容性
【发布时间】:2013-02-15 00:04:04
【问题描述】:

我有这样的文件:

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

但在使用此文件一段时间后,我的客户发现,Str 永远不会大于 100 个字符,而且他还需要其他字段。

在新版本中我们有这样的文件:

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

这条记录的大小相同,在之前的记录中,Str 和 RecType 之间的记录在对齐到 8 个字节时是一个未使用的字节。

问题:发生了什么,什么时候从旧代码中读取这个新文件?他需要向后兼容。

旧代码阅读示例:

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

【问题讨论】:

  • 您需要在问题中提供语言标签。不熟悉 Pascal(或 Delphi)的人不知道您在这里问什么,而没有标签的人可能会错过您的问题。
  • 你能发布一些读取它的代码吗?
  • 在我看来,编写一个以新格式写入一些记录然后尝试使用旧格式读取它们的快速测试应用程序将非常容易;它几乎会立即回答问题,并会为您提供一个测试,您也可以将其用于未来的更改。
  • 我有测试,这是可行的,但我很困惑 - 这是可能的,那个 Str 字段可能是乱码?
  • 抱歉,如果您发布完全不同的记录大小,问题关于记录大小的。 :-) 然后答案变成“不,显然这行不通,因为您正在读取和写入完全不同大小的记录。”。不过,感谢您的快速编辑。 :-)

标签: delphi record backwards-compatibility delphi-5


【解决方案1】:

old school pascal 字符串使用字符串的第一个字节(索引 0)来存储字符串的长度。

我们来看看这条记录的内存:

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

从字节 11 到 242,内存可以包含垃圾,它会被程序简单地忽略(从未显示),因为这会将字节 0 处的值 10 作为字符串的长度,因此字符串变为'ABCDEFGHIJ'

这确保读取使用最新版本创建的文件的旧程序永远不会在字符串末尾看到 garbage,因为该字符串的 view 将是限于字符串的实际大小,内存位置会被忽略。

您必须仔细检查旧程序是否不会更改存储的值,以防它将记录写回文件。我认为它也是安全的,但我只是不确定并且手头没有 Delphi 可以测试。

【讨论】:

  • 我认为字符串格式和旧程序客户相同,无需编辑即可查看数据
  • 很好解释,但问题是关于旧代码读取新记录。由于旧记录将字符串定义为大 50 个字节,它确实可能包含一个以某种方式丢失的字符串,该字符串比新记录中的 200 个字符长(例如,如果存储了一个实际的 250 个字节的字符串,或者一个由于某种原因用空格填充)。
  • 所有记录不包含超过100个字符的字符串
  • @Ken 一个 新记录 不能超过 200 条,所以旧代码不会弄乱它。无论如何,问题在于新代码读取旧记录,因为理论上一个字符串可能超过 200。
  • @Ken,是的,但问题是读取这些值是否安全,而不是写入它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2011-02-06
  • 2016-02-20
相关资源
最近更新 更多