首页 > 解决方案 > 为什么 Delphi 7 在附加模式下打开时会在 ASCII 码 14 后截断文件?

问题描述

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

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.

我希望它创建a.txt包含文件"before#14after#13#10",然后不附加任何内容。但是,在 Windows 上运行该程序后,我看到beforea.txt,就像 Delphiappend截断文件一样。如果我不重新打开文件,它会before#14after#13#10按预期显示。

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

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

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

标签: delphiascii

解决方案


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

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

注意:如果文件的最后 128 字节块中存在 Ctrl+Z (ASCII 26),则设置当前文件位置,以便添加到文件的下一个字符覆盖块中的第一个 Ctrl+Z。通过这种方式,可以将文本附加到以 Ctrl+Z 结尾的文件中。

我猜是一种CP/M向后兼容性。

TextOpen但是,在for Windows的实现中存在一个错误(请参阅Source/Rtl/Sys/System.pas您的 Delphi 7 安装在第 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. 不幸的是,由于某种原因可以编译,它甚至已经出现在 StackOverflow 上。有一个标签叫做@@eof,差不多就是这样。

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


推荐阅读