ТЕОРЕТИЧЕСКАЯ ЧАСТЬ. Файл – это именованный объект, хранящий данные (программу или любую другую информацию) на каком-либо носителе (дискете
Файл – это именованный объект, хранящий данные (программу или любую другую информацию) на каком-либо носителе (дискете, винчестере, CD) [1]. В языке С файлом может быть все, начиная с дискового файла и заканчивая терминалом или принтером [2]. Поток связывают с определенным файлом, выполняя операцию открытия, после которой можно проводить обмен информацией между файлом и программой. Не у всех файлов одинаковые возможности. Например, к дисковому файлу прямой доступ возможен, в то время как к некоторым принтерам – нет. В языке С все потоки одинаковы, а файлы – нет [2]. Если файл может поддерживать запросы на местоположение (указатель текущей позиции), то при его открытии указатель устанавливается в начало файла. При чтении из файла (или записи в него) каждого символа указатель текущей позиции увеличивается, обеспечивая тем самым продвижение по файлу [2]. Файл отсоединяется от определенного потока (т. е. между файлом и потоком разрывается связь) с помощью операции закрытия. При закрытии файла, открытого с целью вывода, содержимое (если оно есть) связанного с ним потока записывается на внешнее устройство. Этот процесс, который обычно называют дозаписью потока, гарантирует, что никакая информация случайно не останется в буфере диска. Если программа завершает работу нормально, т. е. либо функция main() возвращает управление операционной системе, либо вызывается функция exit(), то все файлы закрываются автоматически. В случае аварийного завершения программы, например краха или вызова функции abort(), файлы не закрываются [2]. Файловая система языка С предназначена для работы с самыми разнообразными устройствами, в том числе с терминалами, дисками и накопителями на магнитной ленте. Даже если какое-то из них сильно отличается от других, буферизованная файловая система все равно представит его в виде логического устройства, которое называется потоком. Потоки бывают двух видов: текстовые и двоичные [2]. Текстовый поток – это последовательность символов. В стандарте С считается, что текстовый поток организован в виде строк, каждая из которых заканчивается символом новой строки. Однако в конце последней строки этот символ не обязателен. В текстовом потоке по требованию базовой среды могут происходить преобразования символов. Например, символ новой строки может быть заменен парой символов – возврата каретки (например, \r) и перевода строки (например, \n), т. е. \r\n. Двоичные потоки – это последовательность байтов, которая взаимно однозначно соответствует байтам на внешнем устройстве, причем никакого преобразования символов не происходит [2]. Кроме того, количество тех байтов, которые пишутся (читаются), и тех, которые хранятся на внешнем устройстве, одинаково. Однако в конце двоичного потока может добавляться определяемое приложением количество нулевых байтов. Они могут использоваться, например, для заполнения свободного места в блоке памяти незначащей информацией, чтобы она полностью заняла сектор на диске. Файловая система языка С состоит из нескольких взаимосвязанных функций [2]. Самые распространенные из них показаны в табл. 12.1.
Для приведенных функций требуется подключить заголовок <stdio.h>. Запись или чтение из файла осуществляются с помощью указателя. Указатель файла – это указатель на структуру типа FILE. Для объявления переменной – указателя файла, например *fp, используется оператор FILE *fp; Идентификатор FILE представляетсобой своеобразный тип данных, а указатель *fp содержит адрес объекта этого типа. Указатель файла указывает на структуру, содержащую различные сведения о файле, его имени, статусе и указателе текущей позиции в начало файла [2]. Открытие файла осуществляется с помощью функции fopen() (fopen_s() в Visual Studio 2010), которая открывает поток и связывает с ним определенный файл. Прототип функции fopen() такой: FILE *fopen(const char**file_name, const char**mode); Здесь формальные переменные имеют следующий смысл: file_name – это имя файла с заданным расширением и возможным путем расположения, mode – режим работы файла: чтение, запись и т. д. [1]. В табл. 12.2 [2], приводятся допустимые значения режимов для функции fopen().
Например, для записи в файл с именем (и расширением) data.txt на диск D следует использовать такие объявление и операции: FILE *fp; fp = fopen("D: \\data.txt", "w"); fprintf(fp, "\n\t hello, world\n"); fclose(fp); В приведенном фрагменте С -кода функция fclose() закрывает поток, который был открыт с помощью вызова функции fopen(). Функция fprintf() осуществляет форматную запись (в данном случае строку hello, world) в файл. Все манипуляции с файлом происходят между функциями fopen() и fclose(). Режим функции fopen() задается строкой "w", которая обеспечивает создание текстового файла для записи. Это означает, что файл data.txt создается на диске D и в него записывается строка hello, world с отступом от верхнего и левого краев. Прототип функции fclose() следующий: int fclose(FILE *fp); Здесь *fp – указатель файла, возвращенный в результате вызова функции fopen() [2]. Возвращение нуля означает успешную операцию закрытия. В случае ошибки возвращается EOF. Обычно отказ при выполнении функции fclose() наблюдается только тогда, когда диск был преждевременно удален из дисковода или на нем не осталось свободного места. Правомочность открытия файла с помощью функции fopen() обычно подтверждается после проверки какой-либо ошибки, например нехватки места для записи или неправильного имени диска, причем ошибка будет обнаружена до того, как программа попытается в этот файл что-либо записать. Поэтому приведенный фрагмент С -кода будет правильным, если производится проверка возможности открытия файла: FILE *fp; if ((fp = fopen("D:\\data.txt", "w")) == NULL) { //exit(1); printf("\n\t Error! Can not open file\n "); printf("\n Press any key: "); getch(); return -1; } fprintf(fp, "\n\t hello, world\n"); fclose(fp); При выполнении условия проверки можно выходить из программы, нажав любую клавишу с заданным сообщением или обратившись к функции exit(), которая в данном фрагменте С -кода закомментирована. В Microsoft Visual Studio 2010 (а также в 2008) рекомендуется применять fopen_s() вместо функции fopen(). Функции, работающие с текстовыми файлами, удобно использовать при создании таких файлов, ведении файлов-протоколов и т. п., а при организации баз данных целесообразно применять функции для работы с бинарными файлами: fwrite() и fread(). Они без каких-либо изменений копируют выделенный блок данных из оперативной памяти в файл и, наоборот [1]. При записи или чтении суффикс "t" (например, "wt") открывает файл в текстовом режиме. Тогда CTRL+Z (символ с кодом 26) обрабатывается как символ конца файла. Кроме того, комбинации символов перевода строки и возврата каретки преобразуются в единственный символ перевода строки ('\n') при вводе, и символы перевода строки – в комбинации символов перевода строки и возврата каретки при выводе. Суффикс "b" открывает файл в бинарном режиме, преобразования символов перевода строки и возврата каретки не производятся.
|