Почему fseek или fflush всегда требуется между чтением и записью в режимах обновления?
Q: Я пытаюсь обновить файл на месте, используя режим fopen
"r+"
, читая определенную строку и записывая измененную строку, но это не работает.
A: Обязательно вызовите fseek
перед тем, как писать, и для поиска возврата к началу строки, которую вы пытаетесь перезаписать, и потому что fseek
или fflush
всегда требуются между чтением и записью в режимах чтения/записи "+". ,
Мой вопрос заключается в том, почему fseek
или fflush
всегда требуются между чтением и записью в режимах чтения/записи "+"? Раздел 5.2 Эндрю Кенига C Traps and Pitfalls (1989) упоминал, что это связано с проблемой обратной совместимости. Кто-нибудь может объяснить подробно?
Ответы
Ответ 1
Библиотека буферизует операции ввода и вывода. Посмотрите setvbuf()
и параметры _IOFBF
, _IOLBF
для этой функции.
fseek()
или fflush()
требуют, чтобы библиотека выполняла буферизованные операции.
Стандарт определяет операцию поиска или сброса как обязательную, чтобы позволить библиотеке некоторые сочетания клавиш; в противном случае для каждой операции ввода-вывода библиотека должна была бы проверить, была ли предыдущая операция также операцией чтения (или операцией записи), и инициировать сброс самостоятельно, если изменилось "направление" ввода-вывода. Имея спецификации как есть, библиотека может предположить, что клиент выполнил поиск/сброс перед изменением направления ввода/вывода.
Ответ 2
Потому что он упрощает код ОС/библиотеки. Файловый поток может иметь отдельные буферы чтения и записи, и для обеспечения их синхронизации всегда требуется дополнительное усилие. Это стоило бы производительности в разы, когда это не было необходимо.
Поэтому вместо этого программисту необходимо сделать это явно, когда это необходимо.
Ответ 3
Прочтите Plauger " Стандартную библиотеку C ", чтобы узнать, почему различные функции стандартной библиотеки (C89) являются такими, какие они есть, и, в частности, почему части стандартной библиотеки ввода-вывода являются такими, какие они есть. Одна из причин заключается в том, что C работает в самых разных системах и с разными средами; устройства, такие как ленты, вполне могут нуждаться в обработке, отличной от той, с которой вы привыкли думать. Кроме того, в Unix рассмотрим ваше "tty" устройство - оно соединяет клавиатуру и мышь с экраном - три совершенно разных аппаратных элемента. Координация между ними достаточно сложна; правила в стандарте делают это проще.
Обратите внимание, что стандарт обязывает это. Это из стандарта C11, ISO/IEC 9899: 2011, но формулировка была аналогичной в предыдущих выпусках:
¶7 Когда файл открывается с режимом обновления ("+" в качестве второго или третьего символа в приведенном выше списке значений аргументов режима), ввод и вывод могут выполняться в связанном потоке. Однако выход не должен быть непосредственно с последующим вводом без промежуточного вызова к fflush
функции или к функции позиционирования файла (fseek
, fsetpos
или rewind
), а вход не должен быть непосредственно с последующим выходом без промежуточного вызова на позиционирование файла функция, если операция ввода не встречает конец файла. Открытие (или создание) текстового файла в режиме обновления может вместо этого открыть (или создать) двоичный поток в некоторых реализациях.