Тема 6 Файловый ввод-вывод
Потоки и файлы
В системе ввода/вывода С для программ поддерживается единый интерфейс, не зависящий от того, к какому конкретному устройству осуществляется доступ. То есть в этой системе между программой и устройством находится нечто более общее, чем само устройство. Такое обобщенное устройство ввода или вывода (устройство более высокого уровня абстракции) называется потоком, в то время как конкретное устройство называется файлом. (Впрочем, файл – тоже понятие абстрактное.) Очень важно понимать, каким образом происходит взаимодействие потоков и файлов.
Потоки ввода-вывода
Файловая система языка С предназначена для работы с самыми разными устройствами, в том числе терминалами, дисководами и накопителями. Даже если какое-то устройство сильно отличается от других, буферизованная файловая система все равно представит его в виде логического устройства, которое называется потоком. Все потоки ведут себя похожим образом. И так как они в основном не зависят от физических устройств, то та же самая функция, которая выполняет запись в дисковый файл, может эту же операцию выполнять и на другом устройстве, например, на консоли. Потоки бывают двух видов: текстовые и двоичные.
|
|
Текстовый поток – это последовательность символов, получаемых путём преобразования данных, хранящихся в оперативной памяти, в данные, хранимые на внешнем устройстве (или наоборот) в соответствии с кодовой таблицей. В стандарте С считается, что текстовый поток организован в виде строк, каждая из которых заканчивается символом новой строки. Однако в конце последней строки этот символ не является обязательным. При этом количество символов, которые пишутся (или читаются), и тех, которые хранятся на внешнем устройстве, может отличаться.
Двоичный поток – это последовательность байтов, которая взаимно однозначно соответствует байтам на внешнем устройстве, причем никакого преобразования символов не происходит. Кроме того, количество тех байтов, которые пишутся (читаются), и тех, которые хранятся на внешнем устройстве, одинаково. Однако в конце двоичного потока может добавляться определённое количество нулевых байтов. Они могут использоваться для заполнения свободного места в блоке памяти незначащей информацией, чтобы она в точности заполнила сектор на диске.
Файлы
В языке С файлом может быть все что угодно, начиная с дискового файла и заканчивая терминалом или принтером. Поток связывают с определенным файлом, выполняя операцию открытия. Как только файл открыт, можно проводить обмен информацией между ним и программой.
|
|
Но не у всех файлов одинаковые возможности. Например, к дисковому файлу прямой доступ возможен, в то время как к некоторым принтерам – нет. Таким образом, важный принцип системы ввода/вывода языка С следующий: все потоки одинаковы, а файлы – нет.
Файл отсоединяется от определенного потока (т.е. разрывается связь между файлом и потоком) с помощью операции закрытия. При закрытии файла, открытого с целью вывода, содержимое связанного с ним потока записывается на внешнее устройство. Если программа завершает работу нормально, то все файлы закрываются автоматически. В случае аварийного завершения работы программы файлы не закрываются.
Основная цель разграничения потоков и файлов – это обеспечить единый интерфейс. Для выполнения всех операций ввода/вывода следует использовать только понятия потоков и применять всего лишь одну файловую систему. Ввод или вывод от каждого устройства автоматически преобразуется системой ввода/вывода в легко управляемый поток.
Основы файловой системы
Файловая система языка С состоит из нескольких взаимосвязанных функций. Самые распространенные из них показаны в таблице 9.1. Они объявлены в заголовочном файле <stdio.h>.
Таблица 6.1. Часто используемые функции файловой системы С
Имя | Действие |
fopen() | Открывает файл |
fclose() | Закрывает файл |
fseek() | Устанавливает указатель записи/чтения файла в определённую позицию |
ftell() | Возвращает текущее значение указателя текущей позиции в файле |
fprintf() | Для файла то же, что printf() для консоли |
fscanf() | Для файла то же, что scanf() для консоли |
feof() | Возвращает значение true (истина), если достигнут конец файла |
ferror() | Возвращает значение true, если произошла ошибка |
remove() | Стирает файл |
fflush() | Дозапись потока в файл |
Указатель файла (файловая переменная) – это то, что соединяет в единое целое всю систему ввода/вывода языка С. Указатель файла – это указатель на структуру типа FILE. Он указывает на структурную переменную, содержащую различные сведения о файле, например, его имя, статус и позицию курсора файла. В сущности, указатель файла определяет конкретный файл и используется соответствующим потоком при выполнении функций ввода/вывода. Чтобы выполнять в файлах операции чтения и записи, программы должны использовать указатели соответствующих файлов. Пример объявления указателя файла (или файловой переменной):
FILE *fp;