Ввод-вывод и работа с файлами

Последнее обновление: 08.01.2023

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

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

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

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

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

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

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

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

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

FILE * fopen(имя_файла, режим_открытия);

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

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

При открытии поток связывается со структурой

Режимы открытия

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Закрытие файла

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

int fclose(указатель_на_поток);

Единственный параметр функции представляет ранее полученный при открытии файла указатель на структуру FILE, связанный с файлом.

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

Например, откроем и закроем файл "data.txt", который расположен в одной и той же папке, что и выполняемая программа:

#include <stdio.h>

int main(void)
{
	FILE * fp = fopen("data.txt", "w");
	fclose(fp);
	return 0;
}

Если файл расположен в каком-то другом месте, то можно указать соответствующий относительный или абсолютный путь. Например, "С:\\data.txt" (если файл data.txt расположен в корне диска C).

Обработка ошибок

В процессе открытия или создания файла мы можем столкнуться с рядом ошибок, например, при открытии в режиме чтения не окажется подобного файла, недостаточно памяти и т.д. И в случае возникновения ошибки функция fopen() возвращает значение NULL. Мы можем обработать возникновение ошибки с помощью проверки результата функции:

#include <stdio.h>
 
int main(void)
{
	FILE * fp= fopen("data28.txt", "r");
	if(fp==NULL)
	{
		perror("Error occured while opening data28.txt");
		return 1;
	}
	
	fclose(fp);
	return 0;
}

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

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

Error occured while opening data28.txt: No such file or directory
Дополнительные материалы
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850