DOS:如何在文件的中间添加文本,而不是重写它?

DOS: How to add text in the MIDDLE of a file, instead of rewriting it?

使用 DOS int 21h API,如何在文件中间写入文本而不是重写它?即执行 "insert" 操作,而不是覆盖。

这不是 asm 问题,而是 DOS 系统调用问题 API。无论您是用 C 编写还是直接用 asm 编写,答案都是一样的。

您需要寻找到插入点,并将从那里到 EOF 的所有内容读入内存。然后写你的新数据,然后再写之前的内容。如果这比您可以分配的内存多,您将需要编写一个新文件。 (复制开头,写下你的新文本,然后复制结尾。)


您可能在想,"why can't you just tell the OS what you want so it can just modify the metadata, instead of forcing you to rewrite the data?"。好吧,因为我假设 DOS 没有为此提供 API。此外,因为它只能以块大小的粒度工作。如果文件其余部分中的文本现在在文件系统数据块中的排列方式不同,则必须重写它。

DOS 是为 FAT 文件系统编写的,花哨的文件分配操作功能似乎更多是最近的创新。显然,大量使用此操作会导致文件碎片化(未在磁盘上连续分配)。或许 SSD 的兴起让没有分片就无法完成的操作得到支持变得更加有趣,因为 Linux 已经获得了对越来越多像这样的操作的支持 fallocate(2).

Linux 支持将块插入现有文件的中间而不重写它们:fallocate(fd, FALLOC_FL_INSERT_RANGE, offset, len), available since Linux 4.1 应该可以做到这一点。

从 Linux 3.15 开始可以使用反向操作,折叠范围而不留空洞。命令行 fallocate(1) utility 支持 fallocate -c.

所有这些操作仅适用于文件系统块大小粒度(通常为 4kiB)。如果您要添加或删除那么多文本,但没有在 4k 边界上排列,您可以使用 fallocate 并且只需要重写相邻页面,而不是整个文件的其余部分。


如果您希望能够高效地执行此操作,请在文件中使用类似于文本编辑器所做的数据结构以允许在任何位置进行高效插入:rope. A gap buffer 不是一个好的选择,因为它一次只维护一个有效的插入点。

可能把 "index" 放在文件的末尾,在所有文本块之后,这样可以很容易地重写。这意味着您不能只将文件提供给其他程序,因为它将采用您的自定义格式。您每次需要时都需要一个工具来生成平面版本,因此磁盘上的绳索仅在您需要比阅读需要更频繁地修改时才有用(对于无法使用自定义库的程序)。