Как можно использовать `fsetpos()`, чтобы разрешить произвольный доступ к файлам, которые слишком велики для обработки с помощью `fseek()`?

Хотя я понимаю, что fpos_t является непрозрачным типом, предназначенным для инициализации функцией fgetpos(), §7.19.9.1 документа Обоснование C99 гласит, что:

fgetpos и fsetpos были добавлены в C89, чтобы разрешить операции произвольного доступа к файлам, которые слишком велики для обработки с помощью fseek и ftell.

и §7.19.9.2:

Необходимость кодировать как позицию записи, так и позицию внутри записи в значении long может привести к тому, что размер текстовых файлов, в которых могут использоваться fseek и ftell, будет значительно меньше размера двоичных файлов.

...

fgetpos и fsetpos были добавлены для работы с файлами, которые слишком велики для обработки с помощью fseek и ftell.

По-видимому, это в первую очередь касается текстовых файлов (файлов, открытых с помощью mode, за исключением флага b), потому что в некоторых реализациях может потребоваться сохранение двух позиций (позиция записи файла и позиция символа записи), что может значительно уменьшить эффективный диапазон fseek(). и ftell() функций для текстовых потоков.

Тем не менее, я понятия не имею, как это особенно полезно для текстовых потоков, и я, конечно, не понимаю, как это можно эффективно использовать для «произвольного доступа».

Похоже, что единственный способ использовать эти функции — это прочитать каждый символ файла и кэшировать их значения fgetpos()d fpos_t, что в лучшем случае кажется нишевым, поскольку вы почти наверняка не хотите читать где-либо рядом с LONG_MAX символами.

О чем думал «Комитет»? Есть ли обоснование C99?


person gw0    schedule 31.03.2016    source источник


Ответы (1)


Я полагаю, что в некоторых (вероятно, архаичных мэйнфреймах) текстовые файлы хранятся в виде серий «записей» (строк), и поэтому позиция файла состоит как из индекса записи, так и из позиции внутри записи, это то, на что, кажется, ссылается текст обоснования. На уровне операционной системы для операции поиска требуется как индекс записи, так и позиция в записи, а не позиция байта в файле; это приводит к тому, что и индекс записи, и позиция внутри должны быть закодированы в значении long для использования с fseek и ftell. Следовательно, реализация библиотеки должна назначать некоторое количество битов каждому индексу записи и позиции, и это ограничивает количество записей и позицию.

Например, если long имеет 32 бита, то это может быть разделено на 25 битов для индекса записи и 7 битов для позиции в записи (допуская максимальную используемую длину записи 127 и 2^25 ~= 33k записей). Однако система может разрешить большее количество записей большего размера.

(Приведенные утверждения частично являются смутным воспоминанием, а частично выводом из текста обоснования).

Однако реальная проблема с fseek и ftell даже на современных настольных системах заключается в том, что значения long может быть недостаточно для представления полного диапазона позиций в файле. В 32-разрядных системах long обычно составляет 32 бита, но файлы часто могут увеличиваться до размера более 2 ГБ. Поэтому требуется другой механизм для указания смещения файлов.

Я, конечно, не понимаю, как его можно эффективно использовать для «произвольного доступа».

В данном случае под «произвольным доступом» имеется в виду возможность поиска любой точки, которая уже была посещена, то есть вы можете переместить (используя fsetpos) любую позицию, которую вы уже получили (через fgetpos). Речь не идет о поиске произвольной позиции байта. Возможно, «произвольный доступ» — неправильный термин, но я думаю, что они просто хотели отличить его от чисто последовательного доступа.

person davmac    schedule 31.03.2016
comment
+1, но мейнфреймы IBM не более архаичны, чем ASCII или POSIX: www -03.ibm.com/systems/z/index.html - person Andrew Henle; 31.03.2016