Стандартные файлы и функции для работы с ними

. . . . . . . .

Открытие и закрытие потока

Потоковый ввод-вывод

Файл – это именованная область внешней памяти. Файл имеет следующие характерные особенности:

1) имеет имя на диске, что дает возможность программам работать с несколькими файлами;

2) длина файла ограничивается только емкостью диска.

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

Библиотека C++ поддерживает три уровня ввода-вывода:

1) потоковый ввод-вывод;

2) ввод-вывод нижнего уровня;

3) ввод-вывод для консоли портов (зависит от конкретной ОС).

На уровне потокового ввода-вывода обмен данными производится побайтно, т.е. за одно обращение к устройству (файлу) производится считывание или запись фиксированной порции данных (512 или 1024 байта). При вводе с диска или при считывании из файла данные помещаются в буфер ОС, а затем побайтно или порциями передаются программе пользователя. При выводе в файл данные также накапливаются в буфере, а при заполнении буфера записываются в виде единого блока на диск. Буферы ОС реализуются в виде участков основной памяти. Таким образом, поток – это файл вместе с предоставленными средствами буферизации. Функции библиотеки C, поддерживающие обмен данными на уровне потока позволяют обрабатывать данные различных размеров и форматов. При работе с потоком можно:

1) открывать и закрывать потоки (при этом указатели на поток связываются с конкретными файлами);

2) вводить и выводить строки, символы, форматированные данные, порции данных произвольной длины;

3) управлять буферизацией потока и размером буфера;

4) получать и устанавливать указатель текущей позиции в файле.

Прототипы функций ввода-вывода находятся в заголовочном файле <stdio.h>, который также содержит определения констант, типов и структур, необходимых для обмена с потоком.

 

Прежде, чем начать работать с потоком, его надо инициировать, т. е. открыть. При этом поток связывается со структурой предопределенного типа FILE, определение которой находится в файле <stdio.h>. В структуре находится указатель на буфер, указатель на текущую позицию и т.п. При открытии потока возвращается указатель на поток, т.е. на объект типа FILE. Указатель на поток должен быть объявлен следующим образом:

#include <stdio.h>

FILE*f; //указатель на поток

 

Указатель на поток приобретает значение в результате выполнения функции открытия потока:

FILE* fopen(const char*filename,const char*mode);

где const char*filename – строка, которая содержит имя файла, связанного с потоком,

const char*mode – строка режимов открытия файла.

 

Пример 108.

f=fopen(“t.txt”,”r”);

где t.txt – имя файла, r – режим открытия файла.

 

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

Таблица 19

Режимы открытия файла, связанного с потоком

 

Режим Описание режима открытия файла  
r Файл открывается для чтения, если файл не существует, то выдается ошибка при исполнении программы
w Файл открывается для записи, если файл не существует, то он будет создан, если файл уже существует, то вся информация из него стирается
a Файл открывается для добавления, если фай не существует, то он будет создан, если существует, то информация из него не стирается, можно выполнять запись в конец файла
r+ Файл открывается для чтения и записи, изменить размер файла нельзя, если файл не существует, то выдается ошибка при исполнении программы
w+ Файл открывается для чтения и записи, если файл не существует, то он будет создан, если файл уже существует, то вся информация из него стирается
a+ Файл открывается для чтения и записи, если файл не существует, то он будет создан, если существует, то информация из него не стирается, можно выполнять запись в конец файла

 

 

Поток можно открывать в текстовом (t) или двоичном режиме (b).

В текстовом режиме поток рассматривается как совокупность строк, в конце каждой строки находится управляющий символ ‘\n’.

В двоичном режиме поток рассматривается как набор двоичной информации.

Текстовый режим устанавливается по умолчанию.

В файле stdio.h определена константа EOF, которая сообщает об окончании файла (отрицательное целое число).

При открытии потока могут возникать следующие ошибки:

1) файл, связанный с потоком не найден (при чтении из файла);

2) диск заполнен (при записи);

3) диск защищен от записи (при записи) и т.п.

В этих случаях указатель на поток приобретет значение NULL (0). Указатель на поток, отличный от аварийного не равен 0.

Для вывода об ошибке при открытии потока используется стандартная библиотечная функция из файла <stdio.h>:

void perror (const char*s);

Эта функция выводит строку символов, на которую указывает указатель s, за этой строкой размещается двоеточие пробел и сообщение об ошибке. Текст сообщения выбирается на основании номера ошибки. Номер ошибки заносится в переменную int errno (определена в заголовочном файле errno.h).

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

Открытые файлы после окончания работы рекомендуется закрыть явно. Для этого используется функция:

int fclose(FILE*f);

Изменить режим работы с файлом можно только после закрытия файла.

 

Пример 109

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

void main()

{

FILE *f;

char filename[20];

cout<<”\nEnter the name of file:”; cin>>filename;

if (f=fopen(filename,”rb”)==0) /*открываем для чтения в бинарном режиме и проверяем*/

// возникает ли ошибка при открытии файла

{

perror(strcat“error in

file :”,filename); //strcat складывает две строки

exit(0); //выход из программы

}

. . . . .

fclose(f);

}

Для текстового файла:

if (f=fopen(filename,”rt”)==0) /*открываем для чтения и проверяем возникает ли ошибка при открытии файла*/

if (f=fopen(filename,”r”)==0) /*открываем для чтения и проверяем возникает ли ошибка при открытии файла.*/

 

Когда программа начинает выполняться, автоматически открываются несколько потоков, из которых основными являются:

1. стандартный поток ввода (stdin);

2. стандартный поток вывода (stdout);

3. стандартный поток вывода об ошибках (stderr).

По умолчанию stdin ставится в соответствие клавиатура, а потокам stdout и stderr – монитор. Для ввода-вывода с помощью стандартных потоков используются функции:

1. getchar()/putchar() – ввод-вывод отдельного символа;

2. gets()/puts() – ввод-вывод строки;

3. scanf()/printf() – форматированный ввод/вывод.

Функции рассматривались, когда рассматривали строковые и символьные данные. Теперь мы можем связать их со стандартными потоками: ввод осуществляется из стандартного потока stdin, вывод осуществляется в стандартный поток stdout. Аналогично работе со стандартными потоками выполняется ввод-вывод в потоки, связанные с файлами.