`fsetpos()` 如何用于 "allow random access on files that are too large to handle with `fseek()`?"

How can `fsetpos()` be used to "allow random access on files that are too large to handle with `fseek()`?"

虽然我知道 fpos_t 是一种不透明类型,旨在由 fgetpos() 函数初始化,但 C99 rationale 的第 7.19.9.1 节指出:

fgetpos and fsetpos were added to C89 to allow random access operations on files that are too large to handle with fseek and ftell.

和§7.19.9.2:

The need to encode both record position and position within a record in a long value may constrain the size of text files upon which fseek and ftell can be used to be considerably smaller than the size of binary files.

...

fgetpos and fsetpos were added to deal with files that are too large to handle with fseek and ftell.

这似乎主要关注文本文件(使用 mode 打开的文件,不包括 b 标志),因为某些实现可能需要存储两个位置(一个文件记录位置和一个记录字符位置),这可能会显着减少文本流的 fseek()ftell() 函数的有效范围。

不过,我不知道这对文本流特别有用,我当然不明白它如何有效地用于 "random access."

似乎实际使用这些函数的唯一方法是读取文件的每个字符并缓存它们的 fgetpos()d fpos_t 值,这充其量似乎是小众的,因为你几乎肯定不会' 想阅读 LONG_MAX 个字符附近的任何地方。

"the Committee" 在想什么?有没有C99的原理原理?

我相信在某些(可能是 archaic 大型机)系统上,文本文件存储为一系列 "records"(行),因此文件位置由两者组成记录索引和记录中的位置,这似乎是基本原理文本所指的内容。在操作系统级别,查找操作需要记录索引和记录中的位置,而不是文件中的字节位置;这导致了记录索引和位置都必须在 long 值内编码以便与 fseekftell 一起使用的问题。因此,库实现需要为每个记录索引和位置分配一些位数,这限制了记录的数量和位置。

例如,如果 long 有 32 位,那么这可能分为 25 位用于记录索引和 7 位用于记录中的位置(允许最大可用记录长度为 127,并且2^25 ~= 33k 条记录)。然而,系统可能允许比这更多更大的记录。

(以上说法一部分是模糊的回忆,一部分是从理据文中推断出来的)

然而,即使在现代桌面系统上,fseekftell 的真正问题是 long 值可能不足以表示文件位置的全部范围。在 32 位系统上 long 通常是 32 位,但文件通常仍然可以增长到大于 2GB。因此需要一种不同的机制来指定文件偏移量。

I certainly don't understand how it could effectively be used for "random access."

在这种情况下"random access"他们所说的是能够寻找到任何已经访问过的点,也就是说,你可以重新定位(使用fsetpos)任何位置你已经获得了(通过fgetpos)。它与寻找任意字节位置无关。可以说 "random access" 是错误的术语,但我认为他们只是想与纯粹的顺序访问区分开来。