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


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

Как правило, взаимодействие между приложением и файлами производится посредством обмена блоков байт фиксированной длины (обычно длина представляет степень двойки - 256 или 512 байт).

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

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

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

Файл вместе с предоставляемыми средствами буферизации представляет поток.

Язык программирования Си содержит необходимый функционал для работы с файлами и устройствами ввода-вывода. Для применения его применения в программе необходимо подключить заголовочный файл stdio.h.

Открытие и закрытие потоков
Чтобы работать с потоком, его необходимо открыть. Для открытия потока применяется функция fopen(), которая имеет следующий прототип:

1
FILE * fopen(имя_файла, режим_открытия);
Первый параметр представляет имя открываемого файла, а второй задает режим открытия, от которого зависит, как файл может быть обработан.

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

При открытии поток связывается со структурой
Режимы открытия
Каждый режим задается в виде набора символов. В частности, мы можем использовать следующие режимы:

"w": текстовый файл открывается для записи. Если файл ранее существовал, то он пересоздается и записывается заново

"r": текстовый файл открывается для чтения

"a": текстовый файл открывается для добавления в него новых данных. Если файл существовал ранее, то данные просто добавляются

"w+": текстовый файл создается для записи/записи. Если файл ранее существовал, то при первой записи после открытия он пересоздается и записывается заново. А при последующих записях после открытия данные добавляются в него без перезаписи.

"r+": текстовый файл открывается для чтения/записи. Запись допустима в любом месте файла, кроме конца файла, то есть недопустимо увеличение размеров файла.

"a+": текстовый файл открывается или создается (при его отсутствии) для чтения/записи. В отличие от режима w+ файл при открытии не пересоздается заново, а в отличии от режима r+ можно записывать данные в конец файла

"wb": бинарный файл открывается для записи

"rb": бинарный файл открывается для чтения

"ab": бинарный файл открывается для дозаписи

"w+b": бинарный файл создается для записи/чтения

"r+b": бинарный файл открывается для чтения/записи

"a+b": бинарный файл открывается или создается (при его отсутствии) для чтения/дозаписи

Режимы позволяют разграничить доступ к файлу и открыть его только для чтения или только для записи или совместить оба варианта. Кроме того, на уровне режимов происходит разделение файлов на текстовые и бинарные. И программа будет обрабатывать файлы определенным образом, в зависимости какой режим будет выбран - для текстовых или бинарных файлов. Неправильно заданный режим может привести к некорректной интерпретации файла.

Закрытие файла
После завершения работы с файлом его следует закрыть. Для этого применяется функция fclose():

1
int fclose(указатель_на_поток);
Единственный параметр функции представляет ранее полученный при открытии файла указатель на структуру FILE, связанный с файлом.

Функция возвращает число: 0 - в случае успешного выполнения и встроенное значение EOF в случае ошибки.

Например, откроем и закроем файл "D:\data.txt":

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(void)
{
FILE * fp = fopen("D:\data.txt", "w");
fclose(fp);
return 0;
}
Обработка ошибок
В процессе открытия или создания файла мы можем столкнуться с рядом ошибок, например, при открытии в режиме чтения не окажется подобного файла, недостаточно памяти и т.д. И в случае возникновения ошибки функция fopen() возвращает значение NULL. Мы можем обработать возникновение ошибки с помощью проверки результата функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
FILE * fp;
if((fp= fopen("D:\data28.txt", "r"))==NULL)
{
perror("Error occured while opening data28.txt");
exit(0);
}

fclose(fp);
return 0;
}
Для вывода ошибки на консоль применяется встроенная функция perror(). И так как дальнейшие действия в программе в случае ошибки при открытии файла смысла не имеют, то с помощью вызова exit(0) завершаем работу приложения.

И если при попытке открытия файла по указанному пути его не окажется, то консоль выведет следующую ошибку:

Error occured while opening data28.txt: No such file or directory