Файл в языке Си рассматривается как неструктурированная последовательность байтов. С этой точки зрения в языке программирования 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