Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЗФ_ОАиП / Лекции ГГУ Скорины - Программирование.doc
Скачиваний:
179
Добавлен:
21.03.2016
Размер:
2.27 Mб
Скачать

28.8. Другие средства для работы с файлами

Функция feof(). Данная функция (на самом деле это макрос) позволяет определить, достигнут ли конец файла. Прототип функции:

int feof(FILE *fp)

Функция feof() возвращает ненулевое значение, если при последней операции ввода из файла был обнаружен конец файла, и 0 в противном случае. Можно использовать как для двоичных, так и для текстовых файлов.

Задача. Ввести из файла неопределенной количество чисел типа long.

void main(void) {

FILE *fp;

long t;

if((fp=fopen("in", "r")) == NULL) {

printf("Ошибка открытия файла\n"); return;

}

fscanf(fp, "%ld", &t);

while (!feof(fp)) {

printf("%ld\n", t);

fscanf(fp, "%ld", &t);

}

fclose(fp);

}

Обратить внимание! Функция feof() возвращает ненулевое значение, только если была попытка чтения чего-либо после конца файла. Поэтому код ниже является ошибочным (последнее введенное из файла число на экране будет отображено дважды).

while (!feof(fp)) {

fscanf(fp, "%ld", &t);

printf("%ld\n", t);

}

Функции fflush() и flushall(). Данные функции применяются для флэширования потоков (одного конкретного потока или всех открытых потоков). Прототипы функций:

int fflush(FILE *fp);

int flushall();

Если заданный поток fp открыт для вывода, то функция fflush() записывает все данные, находящиеся в буфере, в соответствующий файл Если поток открыт для ввода, то функция fflush() очищает содержимое буфера (следующая операция чтения считывает новые данные из входного файла в буфер). После вызова функции поток остается открытым. После своего успешного выполнения функция fflush() возвращает нуль, в противном случае – EOF.

Функция flushall() выполняет действия, аналогичные fflush(), только не для одного конкретного потока, а для всех открытых потоков. Функция возвращает количество открытых потоков (входных и выходных). В случае ошибки возвращаемого значения нет.

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

Произвольный доступ к файлам. Ввод/вывод обычно бывает последовательным, т. е. каждая новая операция чтения/записи имеет дело с позицией файла, следующей за той, что была в предыдущей операции чтения/записи. Другими словами, при последовательном доступе файл читается или пишется последовательно байт за байтом. Операции ввода/вывода начинаются с текущей позиции в файле. Указатель чтения/записи в файле изменяется после каждой операции чтения или записи. Например, при чтении символа из файла указатель продвигается на 1 байт, так что следующая операция начнется с первого несчитанного символа. Для того, чтобы получить доступ к байту с номером К, необходимо просмотреть (прочитать или записать) от начала файла К-1 предшествующих байтов. После обращения к байту с номером К можно обращаться к байту с номером К+1. Если файл открыт для добавления, указатель файла автоматически устанавливается на конец файла перед каждой операцией записи.

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

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

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

Обычно прямой доступ используют для файлов, открытых в двоичном режиме. Причина тут простая – так как в текстовом режиме могут выполняться преобразования символов, то может и не быть прямого соответствия между тем, что находится в файле и тем байтом, к которому нужен доступ. Даже если в файле находится один только текст, все равно этот файл при необходимости можно открыть и в двоичном режиме. Никакие ограничения, связанные с тем, что файлы содержат текст, к операциям прямого доступа не относятся. Эти ограничения относятся только к файлам, открытым в текстовом режиме.

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

Функция rewind(). Данная функция устанавливает указатель текущей позиции в файле на начало файла. Прототип функции:

void rewind(FILE *fp);

Функция fseek(). Данная функция предоставляет способ передвигаться по файлу, не читая и не записывая данные, т.е. устанавливает указатель текущей позиции в файле. Функция fseek() позволяет нам обрабатывать файл подобно массиву. Прототип функции:

int fseek(FILE *fp, long offset, int from_where);

Параметр offset определяет, как далеко следует передвинуться от начальной точки, заданной параметром from_where. Он должен иметь значение типа long, которое может быть положительным (движение вперед) или отрицательным (движение назад). Параметр from_where определяет, откуда отсчитывать смещение offset: значение SEEK_SET – от начала файла; SEEK_CUR – от текущей позиции указателя чтения/записи в файле; SEEK_END – от конца файла. Функция вернет 0, если указатель успешно перемещен, в противном случае – вернет ненулевую величину (-1).

Функция ftell(). Данная функция возвращает текущее положений указателя чтения/записи в файле. Прототип функции:

long ftell(FILE *fp);

Позиция указателя чтения/записи отсчитывается от начала файла, начиная с 0. В случае ошибки функция вернет -1.

Значение, возвращаемое fteel(), физически не отражает байтового смещения offset для файла, открытого в текстовом режиме, т.к. текстовый режим преобразует комбинации символов. Для текстового режима надо использовать функцию ftell() с параметром offset=SEEK_SET совместно с fseek(), чтобы корректно запомнить и восстановить месторасположения указателя в файле.