Выше мы рассмотрели последовательный доступ к данным. Все функции работы с файлами после выполнения действия (чтения или записи) автоматически передвигают файловый указатель на следующий элемент данных, таким образом обеспечиваю последовательный перебор данных. Если требуется выборочная работа с данными, необходимо использовать функции произвольного перемещения файлового указателя. Для этой цели используются четыре функции:
1) функция rewind() перемещает указатель (курсор) файла в начало файла.
Прототип функции
void rewind(FILE *fp);
2) функция fseek() устанавливает курсор файла в заданную позицию.
Прототип функции
int fseek(FILE *fp, long delta, int begin);
Здесь fp – указатель на файл, delta – смещение относительно «начала отсчета» (в байтах), begin – макрос, определяющий «начало отсчета».
Имена макросов представлены в таблице 5
Таблица 5
Начало отсчета
Имя макроса
Начало файла
SEEK_SET
Текущая позиция
SEEK_CUR
Конец файла
SEEK_END
3) Функция ftell() определяет текущую позицию файлового указателя относительно начала файла.
Прототип функции
Long int ftell (FILE *fp);
4) Функция int feof (FILE *fp) возвращает истинное значение, если обнаружен «конец файла».
Пример 18. Работа с текстовым файлом. Прочитать каждый второй символ файла.
…
void main()
{int i;
FILE *fp;
const int n=50;
char sim;
if ((fp = fopen(“text1.txt”, “r”)==NULL)
{ puts(“Nevozmogno otkrit’ file”);
exit(1)
}
//вывод всего текста на экран (без пропусков)
while (!feof(fp)) //продолжить, пока не конец файла
{ sim = fgets(fp); //чтение символа из файла
putchar(sim); //вывод символа на экран
};
putchar(‘\n’);
rewind (fp); //переместить файловый указатель в начало
sim = fgets(fp); //чтение символа из файла
while (!feof(fp))
{ putchar(sim);
//Переместить указатель на одну позицию
fseek(fp, 1, SEEK_CUR);
sim = fgets(fp);
};
putchar(‘\n’);
fclose(fp);
}
Это были функции файлового ввода / вывода в стиле языка С. В языке С++ ввод/вывод практически ничем не отличается от аналогичных функций в С.
Рассмотрим некоторые моменты
5. Функции ввода / вывода в стиле С++
Работа с потоком начинается с его открытия. Поток можно открыть для чтения и / или записи в двоичном или текстовом режиме. Функции открытия потока имеет формат:
При успешном открытии потока функция возвращает указатель на предопределенную структуру типа FILE, содержащую всю необходимую для работы с потоком информацию, или NULL в противном случае. Первый параметр – имя отрываемого файла в виде С-строки, второй – режим открытия файла:
“r” – файл открывается для чтения,
“w” – открывается пустой файл для записи (если файл существует, он стирается),
“a” – файл открывается для добавления информации в его конец,
“r+” – файл открывается для чтения и записи (файл должен существовать),
“w+” – открывается пустой файл для чтения и записи (если файл существует, он стирается),
“a+” – файл открывается для чтения и добавления информации в его конец.
Т.е. все в соответствии с таблицей 3.
Режим открытия может также содержать символы t (текстовый режим) или b (двоичный режим), отличающиеся обработкой символов перехода на новую строку. По умолчанию файл открывается в текстовом режиме.
Пример 19.
FILE *f = fopen(“d:\\cpp\\data”, “rb+”);
Указатель f используется в дальнейших операциях с потоком. Его передают функциям ввода / вывода в качестве параметра.
При открытии потока с ним связывается область памяти, называемая буфером. При вводе вся информация направляется в буфер и накапливается там до заполнения буфера или до закрытия потока. Чтение осуществляется блоками, равными размеру буфера, и данные читаются из буфера. Буферизация позволяет более быстро и эффективно обмениваться информацией с внешними устройствами. Следует иметь в виду, что при аварийном завершении программы выходной буфер может быть не выгружен, и возможна потеря данных. С помощью функций setbuf и setvbuf можно управлять размерами и наличием буферов.
Существует пять предопределенных потоков, которые открываются в начале работы программы: стандартный ввод stdin, стандартный вывод stdout, стандартный вывод сообщений об ошибках stderr, стандартный дополнительный поток stdaux и стандартная печать stdprn. Первые три потока по умолчанию относятся к консоли. Эти указатели можно использовать в любой функции ввода / вывода там, где требуется указатель потока.
5.2 Ввод / вывод в поток
Ввод / вывод в поток можно осуществлять различными способами: в виде последовательности байтов, в виде символов и строк или с использованием форматный преобразований. Для каждого вида операций определен свой набор функций.
Операции ввода / вывода выполняются начиная с текущей позиции потока, определяемой положением указателя потока. Указатель устанавливается при открытии на начало или конец файла (в соответствии с режимом открытия) и изменяется автоматически после каждой операции ввода / вывода. Текущее положение указателя можно получить с помощью функций ftell и fgetpos и задать явным образом с помощью функций fseek и fsetpos. Эти функции нельзя использовать для стандартных потоков. Ниже перечислены основные функции ввода/вывода потока (аналогично таблице 4):
Чтение и запись потока байтов выполняют функции fread и fwrite.
Чтение символа из потока - getc, fgetc, из стандартного потока stdin – getchar.
Запись символа в поток - putc, fputc, в стандартный поток stdout – putchar.
Чтение строки из потока - fgets, из стандартного потока stdin – gets.
Запись строки в поток - fputs, в стандартный поток stdout – puts.
Форматированный ввод из потока – fscanf, из стандартного потока stdin – scanf, из строки – sscanf.
Форматированный вывод в поток – fprintf, в стандартный поток stdout – printf, в строку – sprintf.