delphi - 为什么 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 上运行该程序后,我看到before
了a.txt
,就像 Delphiappend
截断文件一样。如果我不重新打开文件,它会before#14after#13#10
按预期显示。
如果我FooBar
在重新打开的文件中写了一些东西 ( ),它会被附加,但好像文件已经被截断:beforeFooBar
.
0 到 32 之间的任何其他字符都不会出现这种效果,即使是 26(代表 EOF)也是如此。
这是 Delphi 中的错误还是定义明确的行为?有什么特别之处chr(14)
?
解决方案
感谢聊天中的一些朋友和评论中的 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 的特殊情况。确切的原因尚未找到。
推荐阅读
- android - 日志中多次出现相同的错误 - processAudioBuffer(34): gainBuffer(192) returned 192 = 128 + 64 err 0
- java - 如何在java(android)中读取没有getAssets的文件
- angular - Chart.js 关闭所有 y 轴并打开/关闭它们
- mouseevent - 图例标签在最新的 Edge Canary 版本中忽略鼠标事件
- python - 训练有关检查点错误的张量流对象检测时出错
- elixir - 在 phoenix elixir 中向数据库插入或更新数据
- mysql - 无限加载数据 MySQL
- regex - 带条件的正则表达式 - 不想要的输出
- javascript - 对象值不更新 javascript
- angular - 全屏模式的网页