В последней главе описаны стандартные устройства ввода и вывода, которые обрабатываются языком программирования C. В этой главе рассказывается, как программисты на C могут создавать, открывать, закрывать текстовые или двоичные файлы для хранения своих данных.
Файл представляет собой последовательность байтов, независимо от того, является ли он текстовым файлом или двоичным файлом. Язык программирования C обеспечивает доступ к функциям высокого уровня, а также к вызовам низкого уровня (уровня ОС) для обработки файлов на ваших устройствах хранения. Эта глава проведет вас через важные призывы к управлению файлами.
Открытие файлов
Вы можете использовать функцию fopen (), чтобы создать новый файл или открыть существующий файл. Этот вызов инициализирует объект типа FILE , который содержит всю информацию, необходимую для управления потоком. Прототип этого вызова функции выглядит следующим образом:
FILE *fopen( const char * filename, const char * mode );
Здесь filename является строковым литералом, который вы будете использовать для именования вашего файла, а режим доступа может иметь одно из следующих значений:
Sr.No. | Режим и описание |
---|---|
1 |
р Открывает существующий текстовый файл для чтения. |
2 |
вес Открывает текстовый файл для записи. Если он не существует, то создается новый файл. Здесь ваша программа начнет запись содержимого с начала файла. |
3 |
Открывает текстовый файл для записи в режиме добавления. Если он не существует, то создается новый файл. Здесь ваша программа начнет добавлять содержимое в существующий файл содержимого. |
4 |
г + Открывает текстовый файл для чтения и записи. |
5 |
ш + Открывает текстовый файл для чтения и записи. Сначала он обрезает файл до нулевой длины, если он существует, в противном случае создает файл, если он не существует. |
6 |
а + Открывает текстовый файл для чтения и записи. Он создает файл, если он не существует. Чтение начнется с самого начала, но запись может быть только добавлена. |
р
Открывает существующий текстовый файл для чтения.
вес
Открывает текстовый файл для записи. Если он не существует, то создается новый файл. Здесь ваша программа начнет запись содержимого с начала файла.
Открывает текстовый файл для записи в режиме добавления. Если он не существует, то создается новый файл. Здесь ваша программа начнет добавлять содержимое в существующий файл содержимого.
г +
Открывает текстовый файл для чтения и записи.
ш +
Открывает текстовый файл для чтения и записи. Сначала он обрезает файл до нулевой длины, если он существует, в противном случае создает файл, если он не существует.
а +
Открывает текстовый файл для чтения и записи. Он создает файл, если он не существует. Чтение начнется с самого начала, но запись может быть только добавлена.
Если вы собираетесь обрабатывать двоичные файлы, вы будете использовать следующие режимы доступа вместо вышеупомянутых:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
Закрытие файла
Чтобы закрыть файл, используйте функцию fclose (). Прототип этой функции —
int fclose( FILE *fp );
Функция fclose (-) возвращает ноль в случае успеха или EOF, если при закрытии файла произошла ошибка. Эта функция фактически сбрасывает любые данные, все еще ожидающие в буфере, в файл, закрывает файл и освобождает любую память, используемую для файла. EOF является константой, определенной в заголовочном файле stdio.h .
В стандартной библиотеке C есть различные функции для чтения и записи файла, символ за символом или в форме строки фиксированной длины.
Написание файла
Ниже приводится простейшая функция для записи отдельных символов в поток.
int fputc( int c, FILE *fp );
Функция fputc () записывает символьное значение аргумента c в выходной поток, на который ссылается fp. Он возвращает письменный символ, написанный при успехе, в противном случае EOF, если есть ошибка. Вы можете использовать следующие функции для записи строки с нулевым символом в конце —
int fputs( const char *s, FILE *fp );
Функция fputs () записывает строку s в выходной поток, на который ссылается fp. Он возвращает неотрицательное значение в случае успеха, в противном случае EOF возвращается в случае любой ошибки. Вы также можете использовать функцию int fprintf (FILE * fp, const char * format, …) для записи строки в файл. Попробуйте следующий пример.
Убедитесь, что у вас есть каталог / tmp . Если это не так, то прежде чем продолжить, вы должны создать этот каталог на вашем компьютере.
#include <stdio.h> main() { FILE *fp; fp = fopen("/tmp/test.txt", "w+"); fprintf(fp, "This is testing for fprintf...\n"); fputs("This is testing for fputs...\n", fp); fclose(fp); }
Когда приведенный выше код компилируется и выполняется, он создает новый файл test.txt в каталоге / tmp и записывает две строки, используя две разные функции. Давайте прочитаем этот файл в следующем разделе.
Чтение файла
Ниже приведена простейшая функция для чтения одного символа из файла —
int fgetc( FILE * fp );
Функция fgetc () читает символ из входного файла, на который ссылается fp. Возвращаемым значением является прочитанный символ, или в случае любой ошибки он возвращает EOF . Следующая функция позволяет читать строку из потока —
char *fgets( char *buf, int n, FILE *fp );
Функция fgets () читает до n-1 символов из входного потока, на который ссылается fp. Он копирует прочитанную строку в буфер buf , добавляя нулевой символ для завершения строки.
Если эта функция встречает символ новой строки ‘\ n’ или конец файла EOF до того, как они прочитают максимальное количество символов, то она возвращает только символы, считанные до этой точки, включая символ новой строки. Вы также можете использовать функцию int fscanf (FILE * fp, const char * format, …) для чтения строк из файла, но она прекращает чтение после обнаружения первого пробела.
#include <stdio.h> main() { FILE *fp; char buff[255]; fp = fopen("/tmp/test.txt", "r"); fscanf(fp, "%s", buff); printf("1 : %s\n", buff ); fgets(buff, 255, (FILE*)fp); printf("2: %s\n", buff ); fgets(buff, 255, (FILE*)fp); printf("3: %s\n", buff ); fclose(fp); }
Когда приведенный выше код компилируется и выполняется, он читает файл, созданный в предыдущем разделе, и выдает следующий результат:
1 : This 2: is testing for fprintf... 3: This is testing for fputs...
Давайте посмотрим немного подробнее о том, что здесь произошло. Во-первых, fscanf () читает именно это, потому что после этого он обнаружил пробел, второй вызов для fgets (), который читает оставшуюся строку, пока не встретит конец строки. Наконец, последний вызов fgets () полностью читает вторую строку.
Двоичные функции ввода / вывода
Есть две функции, которые можно использовать для двоичного ввода и вывода —
size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file); size_t fwrite(const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);
Обе эти функции должны использоваться для чтения или записи блоков памяти — обычно массивов или структур.