Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема 6 Файловый ввод-вывод.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
119.3 Кб
Скачать

6.2 Основы файловой системы

Файловая система языка С состоит из нескольких взаимосвязанных функций. Самые распространенные из них показаны в таблице 9.1. Они объявлены в заголовочном файле <stdio.h>.

Таблица 6.1. Часто используемые функции файловой системы С

Имя

Действие

fopen()

Открывает файл

fclose()

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

fseek()

Устанавливает указатель записи/чтения файла в определённую позицию

ftell()

Возвращает текущее значение указателя текущей позиции в файле

fprintf()

Для файла то же, что printf() для консоли

fscanf()

Для файла то же, что scanf() для консоли

feof()

Возвращает значение true (истина), если достигнут конец файла

ferror()

Возвращает значение true, если произошла ошибка

remove()

Стирает файл

fflush()

Дозапись потока в файл

Указатель файла (файловая переменная) – это то, что соединяет в единое целое всю систему ввода/вывода языка С. Указатель файла – это указатель на структуру типа FILE. Он указывает на структурную переменную, содержащую различные сведения о файле, например, его имя, статус и позицию курсора файла. В сущности, указатель файла определяет конкретный файл и используется соответствующим потоком при выполнении функций ввода/вывода. Чтобы выполнять в файлах операции чтения и записи, программы должны использовать указатели соответствующих файлов. Пример объявления указателя файла (или файловой переменной):

FILE *fp;

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

Функция fopen() открывает поток и связывает с этим потоком определенный файл. Затем она возвращает указатель этого файла. Чаще всего под файлом подразумевается дисковый файл. Прототип функции fopen() такой:

FILE* fopen ( const char *имя_файла, const char *режим_доступа );

где первый параметр имя_файла – это указатель на строку символов, представляющую собой допустимое имя файла, которое может также включать путь к этому файлу, а второй параметр режим_доступа определяет, каким образом файл будет открыт. В таблице 6.2 показаны режимы работы с файлом.

Таблица 6.2. Режимы работы с файлом

Режим

Что означает

r

Открыть текстовый файл для чтения

w

Создать текстовый файл для записи

a

Добавить в конец текстового файла

rb

Открыть двоичный файл для чтения

wb

Создать двоичный файл для записи

ab

Добавить в конец двоичного файла

r+

Открыть текстовый файл для чтения/записи

w+

Создать текстовый файл для чтения/записи

a+

Добавить в конец текстового файла

или создать текстовый файл для чтения/записи

r+b

Открыть двоичный файл для чтения/записи

w+b

Создать двоичный файл для чтения/записи

a+b

Добавить в конец двоичного файла

или создать двоичный файл для чтения/записи

Хотя название большинства файловых режимов объясняет их смысл, сделаем некоторые дополнения. Если попытаться открыть файл только для чтения, а он не существует, то работа fopen() завершится отказом. А если попытаться открыть файл в режиме дополнения, а сам этот файл не существует, то он просто будет создан. Более того, если файл открыт в режиме дополнения, то все новые данные, которые записываются в него, будут добавляться в конец файла. Содержимое, которое хранилось в нем до открытия (если только оно было), изменено не будет. Далее, если файл открывают для записи, но выясняется, что он не существует, то он будет создан. А если он существует, то содержимое, которое хранилось в нем до открытия, будет утеряно, причем будет создан новый файл.

Разница между режимами r+ и w+ состоит в том, что если файл не существует, то в режиме открытия r+ он создан не будет, а в режиме w+ все произойдет наоборот: файл будет создан. Более того, если файл уже существует, то открытие его в режиме w+ приведет к утрате его содержимого, а в режиме r+ оно останется нетронутым.

Динамическая переменная с информацией о файле, которую создаёт и инициализирует функция fopen() и на которую указывает файловая переменная (или указатель файла), имеет следующую структуру:

typedef struct {

unsigned char *curp; // Current active pointer

unsigned char *buffer; // Data transfer buffer

int level; // Fill/Empty level of buffer

int bsize; // Buffer size

unsigned short istemp; // Temporary file indicator

unsigned short flags; // File status flags

wchar_t hold; // Ungetc char if no buffer

char fd; // File descriptor

unsigned char token; // Used for validity checking

} FILE;

В функции fopen() можно задать конкретное имя файла или предоставить выбор имени пользователю.

1) задание конкретного имени файла:

FILE *fp;

fp = fopen ( "file.txt", "wt" );

2) имя файла выбирает пользователь:

FILE *fp;

char FileName[16];

printf ( "\n Enter file name " );

scanf ( "%s", FileName ); // или scanf( "%s", &FileName[0] );

fp = fopen ( FileName, "wt" );

Функция fopen() возвращает указатель файла. Никогда не следует изменять значение этого указателя в программе. Если при открытии файла происходит ошибка, то fopen() возвращает пустой (NULL) указатель.

Хотя предыдущий код технически правильный, но его обычно пишут немного по-другому:

FILE *fp;

fp = fopen("file.txt", "wt");

if ( fp == NULL ) {

printf ( "\n Error opening the file \n");

exit(1);

}

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

Максимальное число одновременно открытых файлов определяется константой FOPEN_MAX. Это значение не меньше 8, но чему оно точно равняется – это должно быть написано в документации по компилятору.

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

Функция fclose() закрывает поток, который был открыт с помощью вызова fopen(). Функция fclose() записывает в файл все данные, которые еще оставались в дисковом буфере, и проводит официальное закрытие файла на уровне операционной системы. Отказ при закрытии потока влечет всевозможные неприятности, включая потерю данных, испорченные файлы и возможные периодические ошибки в программе. Функция fclose() также освобождает блок управления файлом, связанный с этим потоком, давая возможность использовать этот блок снова. Так как количество одновременно открытых файлов ограничено, то, возможно, придется закрывать один файл, прежде чем открывать другой. Прототип функции fclose():

int fclose (FILE *уф);

где уф – указатель файла, возвращенный в результате вызова fopen(). Возвращение нуля означает успешную операцию закрытия. В случае же ошибки возвращается EOF. Чтобы точно узнать, в чем причина этой ошибки, можно использовать стандартную функцию ferror() (о которой вскоре пойдет речь). Обычно отказ при выполнении fclose() происходит только тогда, когда диск был преждевременно удален (стерт) с дисковода или на диске не осталось свободного места.