Как на самом деле feof () узнает, когда достигнут конец файла?

Я новичок в C ++ и пытаюсь лучше понять feof(), Я прочитал это feof() Флаг устанавливается в true только после попытки прочитать за конец файла, так много раз начинающие читают еще раз, чем они ожидали, если они делают что-то вроде while(!feof(file)), Однако я пытаюсь понять, как на самом деле интерпретируется попытка чтения после конца файла? Весь файл уже прочитан и количество символов уже известно или есть какой-то другой механизм в работе?

Я понимаю, что где-то это может быть повторяющийся вопрос, но я не смог его найти, возможно, потому, что не знаю, как лучше сказать, что я спрашиваю. Если ответ уже есть, ссылка будет весьма полезна. Благодарю.

6

Решение

Что бы ни делала библиотека C ++, в конце концов она должна читать из файла. Где-то в операционной системе есть фрагмент кода, который в конечном итоге обрабатывает это чтение. Он получает от файловой системы длину файла, сохраненную таким же образом, как файловая система хранит все остальное. Зная длину файла, позицию чтения и количество считываемых байтов, можно определить, что низкоуровневое чтение достигает конца файла.

Когда это определение сделано, оно передается вверх по стеку. В конце концов, он попадает в стандартную библиотеку, которая внутренне записывает, что конец файла достигнут. Когда запрос на чтение в библиотеку пытается пройти этот записанный конец, устанавливается флаг EOF и feof начнет возвращать истину.

10

Другие решения

feof() является частью стандартной библиотеки C буферном I / O. Так как это буферизовано, fread() предварительно читает некоторые данные (определенно не весь файл, хотя). Если при буферизации fread() обнаруживает EOF (базовая подпрограмма ОС возвращает специальное значение, обычно -1), он устанавливает флаг на FILE состав. feof() просто проверяет этот флаг. Так feof() возвращение true по существу означает «предыдущая попытка чтения обнаружена в конце файла».

Как Обнаружено, что EOF зависит от OS / FS и не имеет никакого отношения к библиотеке / языку C. ОС имеет некоторый интерфейс для чтения данных из файлов. Библиотека C — это просто мост между ОС и программой, поэтому вам не нужно менять свою программу, если вы переходите на другую ОС. ОС знает, как файлы хранятся в своей файловой системе, поэтому она знает, как обнаружить EOF. Я предполагаю, что обычно это выполняется путем сравнения текущей позиции с длиной файла, но это может быть не так просто и может включать много низкоуровневых деталей (например, что если файл находится на сетевом диске ?).

Интересным вопросом является то, что происходит, когда поток заканчивается, но он еще не был обнаружен при чтении. Например, если вы открываете пустой файл. Первый звонок feof() перед любым fread() вернуть истину или ложь? Ответ, вероятно, ложный. Документы не очень ясно по этому вопросу:

Этот индикатор обычно устанавливается предыдущей операцией в потоке
который пытался прочитать в конце файла или после него.

Звучит так, как будто конкретная реализация может выбрать другие необычные способы установки этого флага.

8

В большинстве файловых систем хранится мета-информация о файле (включая его размер), а также делается попытка прочитать после окончания результатов установленный флаг feof. Другие, например, старые или облегченные файловые системы, устанавливают feof, когда они приходят к последнему байту последнего блока в цепочке.

3

Как на самом деле feof () узнает, когда достигнут конец файла?

Когда код пытается прочитать прошло последний персонаж.

В зависимости от типа файла последний символ не обязательно известен до тех пор, пока не будет предпринята попытка прочитать его, и символ не будет доступен.


Пример кода, демонстрирующий feof() переходя от 0 до 1

#include <stdio.h>

void ftest(int n) {
FILE *ostream = fopen("tmp.txt", "w");
if (ostream) {
while (n--) {
fputc('x', ostream);
}
fclose(ostream);
}
FILE *istream = fopen("tmp.txt", "r");
if (istream) {
char buf[10];
printf("feof() %d\n", feof(istream));
printf("fread  %zu\n", fread(buf, 1, 10, istream));
printf("feof() %d\n", feof(istream));
printf("fread  %zu\n", fread(buf, 1, 10, istream));
printf("feof() %d\n", feof(istream));
puts("");
fclose(istream);
}
}

int main(void) {
ftest(9);
ftest(10);
return 0;
}

Выход

feof() 0
fread  9  // 10 character read attempted, 9 were read
feof() 1  // eof is set as previous read attempted to read passed the 9th or last char
fread  0
feof() 1

feof() 0
fread  10  // 10 character read attempted, 10 were read
feof() 0   // eof is still clear as no attempt to read passed the 10th, last char
fread  0
feof() 1
3

feof() Функция устанавливает индикатор конца файла при чтении символа EOF. Так когда feof() читает последний элемент, EOF сначала не читается вместе с ним. Поскольку индикатор EOF не установлен и feof() возвращает ноль, поток снова входит в цикл while. Этот раз fgets узнает, что следующим символом является EOF, он отбрасывает его и возвращает NULL, но также устанавливает индикатор EOF. Так feof() обнаруживает индикатор конца файла и возвращает ненулевое значение, прерывая цикл while.

-2
По вопросам рекламы [email protected]