为什么 Delphi 7 在 ASCII 码 14 后以追加模式打开时截断文件?

Why does Delphi 7 truncate file after ASCII code 14 when opening in Append mode?

我正在开发一些用 Delphi 7 编写的遗留软件,运行s 在 Windows 上。我已将问题缩小到以下程序:

var f: text;
begin
  assign(f, 'a.txt');
  rewrite(f);
  writeln(f, 'before' + chr(14) + 'after');
  close(f);

  assign(f, 'a.txt');
  append(f);
  close(f);
end.

我希望它创建包含 "before#14after#13#10"a.txt 文件,然后不向其附加任何内容。但是,在 运行 这个程序在 Windows 之后,我在 a.txt 中看到了 before,就像 Delphi 的 append t运行分类文件。如果我不重新打开文件,它会按预期显示 before#14after#13#10

如果我在重新打开的文件中写了一些东西 (FooBar),它会被追加,但好像文件已经被 t运行cated: beforeFooBar.

对于 0 到 32 之间的任何其他字符,即使是 26(代表 EOF)也不会出现这种效果。

这是 Delphi 中的错误还是明确定义的行为? chr(14)有什么特别之处?

感谢聊天中的一些朋友和评论中的 Sertac Akyuz:它看起来像是 Delphi 7 中的错误。

它应该对 EOF 符号 (ASCII 26) 进行特殊处理,引用自 here:

Note: If a Ctrl+Z (ASCII 26) is present in the last 128-byte block of the file, the current file position is set so that the next character added to the file overwrites the first Ctrl+Z in the block. In this way, text can be appended to a file that terminates with a Ctrl+Z.

有点 CP/M 向后兼容性,我想。

但是,Windows 的 TextOpen 的实现存在一个错误(请参阅 Delphi 7 安装中的 Source/Rtl/Sys/System.pas 大约 4282 行):

@@loop:
        CMP     EAX,EDX
        JAE     @@success

//    if  (f.Buffer[i] == eof)

        CMP     byte ptr [ESI].TTextRec.Buffer[EAX],eof
        JE      @@truncate
        INC     EAX
        JMP     @@loop

这里说的是 eof 而不是 cEof。不幸的是,由于某种原因编译 and it even appeared on Whosebug already。有一个名为 @@eof 的标签,仅此而已。

结果:我们没有 26 的特殊情况,而是 14 的特殊情况。确切原因尚未找到。