Лекция 5 Файлы в Си. Лекция 5 Файлы в Си Понятие файла в языке Си Файл это упорядоченная последовательность однотипных компонентов, расположенных на внешнем носителе
![]()
|
Лекция 5 Файлы в СиПонятие файла в языке СиФайл - это упорядоченная последовательность однотипных компонентов, расположенных на внешнем носителе.Файлы предназначены только для хранения информации, а обработка этой информации осуществляется программами.Использование файлов целесообразно в случае:
Файл, не содержащий ни одного элемента, называется пустым.Создается файл путем добавления новых записей в конец первоначально пустого файла.Длина файла, т.е. количество элементов, не задается при определении файла.В языке Си отсутствуют операторы для работы с файлами. Все необходимые действия выполняются с помощью функций, включенных в стандартную библиотеку ввода-вывода языка Си (stdio.h - standart input output).Буферизация ввода-выводаСчитываемая и записываемая информация представляет собой последовательность байтов - "поток" (stream).Поток – это логическое устройство, являющееся источником или получателем данных.В зависимости от того, откуда поступает считываемая информация или куда направляется записываемая информация, поток связывается с соответствующим устройством ввода вывода (клавиатура, дисплей, принтер и т.п.) или с именованной областью внешней памяти – файлом, если требуется долговременно хранить информацию либо получить доступ к хранимой информации. При организации ввода-вывода в С используется буферизация, то есть обмен информацией между программой и внешним устройством происходит не непосредственно, а через буфер – специально выделяемую системой область оперативной памяти.Буферизация ускоряет работу программы из-за уменьшения количества обращений к внешним устройствам.В библиотеке описана константа BUFSIZE, величина которой 512:#define BUFSIZE 512Для изменения размера буфера предназначены функции setbuf() или setvbuf().Текстовый и бинарный режим работы с файламиБиблиотека stdio.h поддерживает текстовые и бинарные (двоичные) потоки.Текстовый поток – это последовательность строк, каждая из которых заканчивается символом ‘\n’. Операционная среда может потребовать коррекции текстового потока. Например, при вводе текстового потока система преобразует символы возврат каретки 0x13 и перевод строки 0x10 в одиночный символ ‘\n’. При обнаружении в текстовом файле символа с кодом 26 (0x26), т.е. признака конца файла, чтение файла в текстовом режиме заканчивается, хотя файл может иметь продолжение. При выводе текстового потока в среду операционной системы происходит обратное преобразование. Бинарный поток – это последовательность не преобразуемых байтов, представляющих собой некоторые промежуточные данные, которые обладают тем свойством, что если их записать, а затем прочесть той же системой ввода-вывода, то будет получена информация, совпадающая с исходной.Функция fopenПрежде чем читать или записывать информацию в файл, он должен быть открыт функцией fopen и тем самым связан с потоком ввода-вывода. Функция открытия потока возвращает указатель fp на предопределенную в библиотеке stdio.h структуру типа FILE (содержащую всю необходимую для работы с потоком информацию) при успешном открытии потока, или NULL в противном случае.В stdio.h заданы 3 предопределенных потока : stdin (стандартный поток ввода), stdout (стандартный поток вывода), stderr (стандартный поток ошибок)
При открытии файла указатель на файл связывается с конкретным файлом на диске (Если файл не может быть открыт по какой-либо причине, функция возвращает NULL. ) :FILE *fp;fp = fopen(“спецификация файла”, "способ использования файла");“Спецификация файла” (т.е. имя файла и путь к нему) может, например, иметь вид:"c:\\my_prog.txt" - для файла my_prog.txt на диске с: .“Способ использования файла” - определяет режим открытия файла.Режимы открытия файла.r - открыть существующий файл для чтения; w - создать новый файл для записи (если файл с указанным именем существует, то он будет переписан); а - дополнить файл (открыть существующий файл для записи информации, начиная с конца файла, или создать файл, если он не существует); r+ - открыть существующий файл для чтения и записи (Запись и чтение из него допустимы в любом месте файла. Не возможна запись в конец файла); w+ - создать новый файл для чтения и записи (если файл с указанным именем существует, то предыдущее содержимое стирается. Последующие после открытия файла запись и чтение из него допустимы в любом месте файла, в том числе запись разрешена и в конце файла); a+ - дополнить или создать файл с возможностью чтения и записи (Возможна запись в конец файла, не уничтожается содержимое при открытии файла, ); rb - открыть двоичный файл для чтения; wb - создать двоичный файл для записи; аb - дополнить двоичный файл; r+b - открыть двоичный файл для чтения и записи; w+b - создать двоичный файл для чтения и записи; а+b - дополнить двоичный файл с предоставлением возможности чтения и записи; rt - открыть текстовой файл для чтения; wt - создать текстовый файл для записи; at - дополнить текстовый файл; r+t - открыть текстовой файл для чтения и записи; w+t - создать текстовый файл для чтения и записи; a+t - дополнить текстовый файл с предоставлением возможности записи и чтения.Строки вида r+b можно записывать и в другой форме: rb+.Примеры открытия файловFILE *f_in, *f_out;f_in = fopen ("My_file1","r");f_out = fopen ("My_file2","w");Последовательный доступ
12 5 45 67 56● конец файла (end of file, EOF) 12 5 45 67 56● f = fopen("qq.dat", "r"); fscanf ( f, "%d", &x ); Как вернуться назад? ? rewind() Функция fcloseПосле окончания работы с файлом он должен быть закрыт. Закрытие файла (текстового или бинарного) выполняется функцией fclose():fclose(FILE *fp);При этом разрывается связь указателя на файл c внешним набором данных. Освободившийся указатель можно использовать для другого файла.При успешном завершении операции функция fclose( ) возвращает значение нуль. Любое другое значение свидетельствует об ошибке.Пример:fclose(f_in);Проверка признака конца файлаПри каждой операции ввода/вывода происходит перемещение указателя текущей позиции в файле, в какой-то момент указатель достигает конца файла. Структура типа FILE имеет поле – индикатор конца файла. Функция feof() проверяет состояние индикатора конца файла и возвращает значение 0, если конец файла не был достигнут, или значение, отличное от нуля, если был достигнут конец файла. Функция имеет единственный аргумент – указатель на поток типа FILE.Вызов функции:if (! feof(f_in))…проверяет, что конец файла еще не достигнут.Функции ввода/вывода. Функции fgetc() и fputc().Простейший способ выполнить чтение из файла или запись в файл – использовать функции fgetc() или fputc().Функция fgetc() выбирает из файла очередной символ; ей нужно только знать указатель на файл:char Symb = fgetc(f_in);Если при обработке достигается конец файла, то функция fgetc() возвращает значение EOF(end of file).Функция fputc() заносит значение символа Symb в файл, на который указывает f_out. Формат вызова функции:fputc(Symb,f_out);Пример 1. Текст из файла my_char.txtвыводится на экран. Если файл не найден, на экран выводится сообщение "File not found!":#include int main(void){FILE *ptr;unsigned char ch;if ((ptr=fopen("my_char.txt","r"))!=NULL){ch=fgetc(ptr);while (!feof(ptr)){printf("%c",ch);ch=fgetc(ptr);}fclose(ptr);}еlse printf("\nFile not found!");return 0;}В этом примере для чтения из файла используется переменная ptr. При открытии файла производится проверка. Если переменной ptr присвоено значение NULL, то файл не найден; на экран выводится соответствующее сообщение, и программа завершается. Если ptr получила ненулевое значение, то файл открыт. Далее выполняется чтение символов из файла до тех пор, пока не будет достигнут конец файла (!feof(ptr)). Прочитанные символы помещаются в переменную ch, а затем выводятся на экран.Пример 2. Записать в файл буквы, вводимые с клавиатуры.Ввод продолжается до нажатия клавиши F6 или CTRL/z(ввод символа EOF – конца файла):#include int main(void){char c;FILE *out;out=fopen("Liter","w");while ((c=getch( ) )!=EOF)fputc(c,out);fclose(out);return 0;}Функции fscanf() и fprintf()Функции fscanf() и fprintf() выполняют форматированный ввод/вывод.Чтение из файла выполняет функция fscanf():fscanf(f_in,[строка формата],[список адресов переменных]);Функция возвращает количество введенных значений или EOF.Запись в файл осуществляет функция fprintf():fprintf(f_out,[строка формата],[список переменных, констант]);Функция возвращает количество выведенных байт (символов) или EOF.Строка формата функций fscanf() и fprintf() формируется так же, какпри консольном вводе/выводе функциями printf() и scanf().Следует заметить, что вызов функцииfscanf(stdin,[строка формата],[список адресов переменных]);эквивалентен вызовуscanf([строка формата],[список адресов переменных]);Аналогично,fprintf(stdout, [строка формата],[список переменных, констант]);эквивалентноprintf([строка формата],[список переменных, констант]);Пример 1. В программе создается массив, состоящий из четырех целых чисел. Вывести массив в файл:#include #define n 4int main() {int i=0;int array[n]={4,44,446,4466};FILE *out;out=fopen("num_arr.txt","w");for(;i fprintf(out,"%6d",array[i]);fclose(out);return 0; }В результате выполнения программы в файл num_arr.txt будет помещенаследующая информация:
Примеры программ, использующих функции fscanf() и fprintf().#include int main() {int S=0, count=0, numb;FILE *in;if ((in=fopen("num_arr.txt","r"))!=NULL){while (!feof(in)){fscanf(in,"%d",&numb);S+=numb;count++;printf("%d\n", numb);}double aver=(double)S/count;printf("Average=%f\n", aver);fclose(in);}elseprintf("\nФайл не найден!");return 0; }Пример 2. Имеется файл данных, содержащий целые числа, разделенные пробелами. Количество чисел в файле неизвестно. Требуется найти среднее арифметическое значение этих чисел. Чтение чисел из файла выполняется в переменную numb до тех пор, пока не будет достигнут конец файла. Одновременно ведется подсчет количества прочитанных символов в переменной count и накопление суммы прочитанных чисел в переменной S. Переменные S и count целые, поэтому для правильного вычисления среднего арифметического, необходимо выполнить преобразование одной из этих переменных в формат double. #include #include int main() { int bal; char name[15]; FILE *file;if ((file = fopen("1.txt","w")) == NULL) printf("Файл невозможно открыть или создать\n"); else{ for(;;){ scanf ("%d%s", &bal, name); if (bal == 0) break; fprintf(file,"%d %s\n", bal, name); } } fclose(file);return 0; }Пример 3. Ввод имени и балла. FILE *file; объявляем указатель на структуру File ( дескриптор файла ). if ((file = fopen("1.txt","w")) == NULL) функция fopen принимает два параметра. Первый - это имя файла, второй - режим работы с файлом, в котором он будет открыт. В нашем режиме, если файл не существует, то он создается, а если файл уже был, то его содержимое полностью стирается. Эта функция возвращает указатель на структуру FILE , т.е. теперь мы сможем управлять созданным файлом при помощи нашего указателя file. Оператор if тут используется, так как идет проверка указателя на NULL, а NULL может быть, только если файл мы не смогли открыть. fprintf(file,"%d %s\n", bal, name); оператор записывает данные в файл. Принцип действия тот же, какой и у оператора printf, только тут в начале указывается указатель на файл , в который будет производится запись данных. fclose(file); раз данные мы записали и файл нам больше не нужен, то смело может закрывать его, тем самым освобождая ресурсы. Функции чтения и записи для бинарных файлов.Если файл был открыт для двоичных данных, то fread() и fwrite() могут читать и писать любой тип информации. Одно из наиболее полезных применений fread() и fwrite() - это чтение и запись блоков данных типа массивов или структур. Использование fread() и fwrite() для чтения или записи сложных данных более эффективно, чем использование повторяющихся вызовов getc() и putc().Они имеют следующие прототипы:size_t fread (void *buf, size_t size, size_t N, FILE *fp);size_t fwrite (const void *buf, size_t size, size_t N, FILE *fp);buf - это указатель на область памяти, которая получает данные из файла(в случае fread()) или это указатель на информацию, записываемую в файл (в случае fwrite()).size – размер каждого считываемого из файла или записываемого в файл элемента в байтах.N – количество элементов размера size, которые должны быть прочитаны или записаны.fp - это файловый указатель на ранее открытый поток.Функция fread() возвращает число прочитанных элементов. Данное значение может быть меньше, чем N, если был достигнут конец файла или произошла ошибка.Функция fwrite() возвращает число записанных элементов. Данное значение равно N, если не возникла ошибка.Пример записи массива в файл.Следующий фрагмент записывает содержимое массива вещественных чисел balance в файл balance, используя один оператор fwrite(). Далее она читает массив, используя один оператор fread(), и выводит его содержимое. #includeif((fp=fopen("balance", "wb"))==NULL) /* открытие на запись */{ printf("Cannot open file."); return 1; } for(i=0; i<100; i++) balance[i] = (float) i; fwrite(balance, sizeof (balance), 1, fp) ; /* запись всего массива balance в файл*/ fclose(fp); for(i=0; i<100; i++) balance[i] = 0.0; /* обнуление массива */ if((fp=fopen("balance","rb"))==NULL) /* открытие для чтения */ { printf("cannot open file"); return 1; } fread(balance, sizeof (balance), 1, fp); /* чтение за раз всего массива balance */ for(i=0; i<100; i++) printf("%f ", balance [i]); /* вывод содержимого массива balance */ fclose(fp); return 0; }ЗаданиеСоздайте 10 записей, содержащихинформацию о железнодорожныхмаршрутах. В нём должны быть следующиеданные:
Запишите сами вручную эти данные в файл.Затем вам необходимо считать эти данные ивывести их на экран. |