在DOS/FAT中缩小或部分截断文件

4
我被委托编写一个数据收集程序,用于 Unitech HT630,该设备运行的是一种专有的 DOS 操作系统,可以运行一些限制条件下编译为 16 位 MS DOS 的可执行文件。我正在使用 Digital Mars C/C++ 编译器,目前工作得很好。
应用程序的要求之一是数据文件必须是人类可读的纯文本格式,也就是说,该文件可以被导入到 Excel 中或者被 Notepad 打开。我正在使用变长记录格式,类似于 CSV,我已经成功地使用了 C 标准库的文件 I/O 函数来实现它。
在保存记录时,我必须计算更新后的记录是否比当前数据文件中的版本更大或更小。如果更大,我首先将当前记录后面的所有记录向前移动大小差异,然后再保存更新后的记录。EOF 会自动由操作系统扩展以容纳额外的数据。如果更小,则将所有记录向后移动我的计算偏移量。这个方法效果很好,但我发现没有办法修改 EOF 标记或文件大小,以忽略最后一条记录后面的数据。
大多数情况下,记录的大小会增加,因为数据收集程序将在保存记录时填充一些空字段。只有在更正现有条目时或者在记录中的描述性数据比程序在内存中读取的数据长时,记录才会缩小。
在记录缩小的情况下,文件的最后一条记录之后就会留下任何已经存在的数据。我一直在将 EOF 分隔符写入文件中,以表示我的记录的结束位置,并填充剩余的数据,但这样做会导致文件不再干净,直到“增长记录保存”扩展了文件大小覆盖了填充区域。在 unistd.h 中的 truncate() 函数不起作用(我现在认为这只适用于 *nix 系统?)。
我看到一个提出的解决方案是创建第二个文件,并将所有要保存的数据写入到那个文件中,然后删除原始文件。由于我只有 4MB 的磁盘空间可用,如果文件大小小于 2MB 减去我的程序可执行文件和配置文件的大小,则此方法有效,否则会失败。很可能当这个程序投入生产时,用户会得到一个超过 2MB 大小的文件。
我查看了 Ralph Brown's Interrupt ListIBM PC Assembly Language and Programming 中的中断参考,但似乎找不到任何更新文件大小或类似操作的方法。
在DOS中,是否可以在不创建第二个文件的情况下减小文件大小?

FAT文件系统是否存在于闪存上?这可能不是一个问题(取决于使用情况),但以这种方式对文件进行碎片整理将会影响闪存有限的擦除/写入寿命。 - nategoose
@nategoose - 该单元拥有一个RAM驱动器分区和一个256k闪存分区,目前我只在严格使用RAM驱动器。闪存分区仅用于存储程序,而不是数据。 - user65628
一些操作系统,包括DOS,可能会将文件填充到最近的有效扇区大小。从偶数扇区边界开始的文件比那些不是的文件更容易和更快地检索。 - Thomas Matthews
2个回答

4
为了缩小DOS中文件的大小,您需要使用int 21 (ax=4200h, bx=handle, cx:dx=offset)找到截断点,并使用零长度调用写入:int 21 (ax=4000h, bx=handle, cx=0(表示截断)。

0
作为调整记录大小的替代方案,您可以在每个记录末尾添加一个“填充”字段,将其填充到标准大小(例如使用空格或类似字符)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接