Функции потока позволяют осуществлять ввод-вывод данных различными способами. Можно читать и записывать данные как последовательность байтов (двоичные данные) или задавать чтение и запись символов, строк или данных более сложных форматов.
Классификация функций чтения и записи по типу объекта, над которым выполняется операция, и разновидности потока приведены в таблице 2.
Операция чтения и записи для потока начинается всегда с текущей позиции потока, определяемой указателем положения в файле. Начальное положение указателя положения в файле устанавливается при открытии потока и может указывать на начало или конец потока в зависимости от того, с каким режимом доступа открыт поток (режимы “r” и “w” устанавливают поток на начало, а режим “a” на конец). После выполнения операции чтения или записи указатель положения в файле изменяется для того, чтобы отразить новую текущую позицию потока. Например, если из потока был прочитан один символ, указатель положения в файле увеличивается на единицу, чтобы следующая операция чтения начиналась с первого байта после прочитанного.
Таблица 2 – Классификация функций чтения и записи потока
Объект операции
Операция ввода-вывода
Чтение
Запись
из потока stdin
из любого потока
из строки Си
в поток stdout
в любой поток
в строку Си
Последователь-ность байтов
fread()
fwrite()
Отдельный символ
getchar()
fgetchar()
putchar()
fputchar()
Данное типа int
getw()
putw()
Строка
gets()
fgets()
puts()
fputs()
Форматирован-ные данные
scanf()
fscanf()
sscanf()
printf()
fprintf()
sprintf()
Указатель положения в файле можно позиционировать на любое место в потоке. Следующая операция ввода-вывода будет выполняться с указанной позиции, т. е. Позиционирование позволяет осуществлять произвольный ввод-вывод для потока. Библиотека функций языка С предоставляет пять функций для позиционирования указателя положения в файле:
ftell(), fgetpos() – получают текущую позицию указателя положения в файле;
fseek(), fsetpos() – устанавливают текущую позицию указателя;
rewind() – позиционирует указатель на начало потока.
Функция
long ftell (FILE *fp);
возвращает текущее значение указателя позиции в файле для указанного потока. Это значение представляет собой количество байт, на которое указатель отстоит от начала файла. В случае ошибки ftell() возвращает значение -1L.
Пример.
long i;
if ((I = ftell(fp) = = -1L) printf(“Ошибка”);
Функция
int fseek (FILE *fp, long число_байт, int начало);
устанавливает указатель положения в файле, связанном с fp, в соответствии со значениями число_байт и начало. Здесь: число_байт – это длинное целое, содержащее число байт от параметра начало до позиции указателя; начало – это одно из следующих макроопределений, установленных в stdio.h:
Имя Значение Позиция
SEEK_SET 0 Начало файла
SEEK_CUR 1 Текущая позиция
SEEK_END 2 Конец файла
В случае успеха функция fseek() возвращает значение 0, в случае неудачи возвращает ненулевое значение.
П р и м е р ы использования функции fseek():
FILE *fp;
long n;
. . .
fseek(fp, 0L, SEEK_SET); /* позиционирование на начало потока */
fseek(fp, 0L, SEEK_END); /* позиционирование на конец потока */
fseek(fp, nL, SEEK_SET); /* позиционирование на n байт от начала потока */
fseek(fp, nL, SEEK_CUR); /* позиционирование на n байт от текущей позиции */
fseek(fp, -nL, 1); /* позиционирование на n байт до текущей позиции */
fseek(fp, , -nL, 2); /* позиционирует на n байт до конца потока */
fseek(fp, , nL, 2); /* указатель может быть позиционирован за конец потока */
fseek(fp, -nL, 0); /* Ошибка. Попытка установить указатель перед началом */
Функция rewind() устанавливает указатель положения в файле на начало файла. Эквивалентна функции
fseek(fp, 0L, SEEK_SET);
Имеет прототип
void rewind (FILE *fp);
Функции fgetpos() и fsetpos() обычно используются в паре. Функция fgetpos() хранит текущее значение указателя положения в файле, связанном с указателем fp, в некоторой переменной, на которую указывает номер_позиции. Прототип этой функции:
int *fgetpos (FILE *fp, fpos_t номер_позиции);
Функция fsetpos() устанавливает указатель положения в файле, связанном с потоком fp, в позицию, указанную параметром номер_позиции. Прототип этой функции:
int fsetpos (FILE *fp, const fops_t *номер_позиции);
Тип fops_t определен в stdio.h и соответствует типу long int.
В случае случае успешного завершения функции fgetpos() и fsetpos() возвращают значение 0 и при неудаче возвращается ненулевое значение.
Приведенная ниже функция читает группу байтов с использованием fgetpos() и fsetpos(). Позиция указателя положения в файле не меняется.
# include <stdio.h> /* требуется для объявления функции */
long read_bytes (FILE *fp, long n, char *save)
{
long num, /* число прочитанных байт */
pos; /* текущая позиция указателя положения */
num = -1L;
if (fgetpos(fp, &pos) = = 0) /* сохранить текущую позицию указателя */
num = fread(save, 1, num, fp); /* прочитать n байт */
fsetpos(fp, &pos); /* восстановить положение указателя положения */
return num;
}
Если поток открывается для добавления (режим доступа “a”, “a+” и т. д.) операции записи относятся к концу потока, хотя указатель положения может быть переустановлен. Это предохраняет данные в файле от затирания.
Нельзя использовать функции определения и установки указателя положения в файле для потока, представляющего устройство. Использование функций ftell(), fseek(), rewind(), fgetpos() и fsetpos() с любым из стандартных потоков приводит к неопределенным результатам.