На этой странице можно скачать этот файл совершенно бесплатно и без регистрации и без отправки смс, а также без различного рода ограничений.
Скачивайте и учитесь, надеемся, наш сайт помог вам "погрызть гранит науки"
Работа с файлами
Лабораторная работа №9 Работа с файлами Управление ресурсами компьютера из прикладных программ. Файловый обмен в языке С. Библиотечные подпрограммы Си для работы с файлами можно разделить на 2 группы - потоковые и префиксные. И те, и другие обращаются в принципе к одним и тем же вызовам MS DOS, но потоковые выполняют дополнительную буферизацию информации, что приводит к двойной буферизации - на уровне ОС и на уровне библиотечной подпрограммы. Префиксные - это блок-ориентированные функции, обращающиеся к префиксным функциям ОС без дополнительной буферизации и их использование дает выигрыш в производительности при переносе сразу группы байтов за одно обращение к функции. Для обеих групп функций файлового ввода-вывода возможны 2 режима доступа к файлу: текстовый и двоичный. В текстовом режиме производится трансляция символьных кодов 0DH, 0Ah - при чтении из файла в один символ новой строки ‘\n’, а при записи в файл этот символ преобразуется в пару CR LF; кроме того, при считывании символа Ctrl Z считается, что достигнут конец файла и прочитать информацию после этого символа в текстовом режиме не удается. В двоичном режиме никакого преобразования байтов не происходит и не делается никаких предположений об их смысле. Режим доступа к файлу задается при его открытии через параметры библиотечной функции или присвоением значения специальной внешней переменной _fmode, описанной в fcntl.h или stdlib.h и могущей принимать 2 значения: O_BINARY или O_TEXT(по умолчанию). Потоковый ввод-вывод. Поток (stream) - абстрактное понятие, связанное с переносом данных между устройством чтения-записи и потоком этих данных, движущихся мимо устройства (воображаемой головки). Потоком информации можно считать данные на диске или поступающие с клавиатуры или дисплей, или порты ввода-вывода - любое устройство с последовательной структурой информационных записей. Для каждого файла, открытого для доступа через поток, Си создает внутреннюю структурную переменную по шаблону FILE. Открытие файла: FILE *f=fopen(const char * Filename, const char * mode); Строка mode может принимать значения: r - открыть для чтения w - создать для записи с усечением a - открыть для добавления в существующий файл a+ - открыть для обновления или создать для чтения и записи r+ - открыть файл для чтения и записи w+ - открыть файл для чтения и записи b двоичный режим t текстовый режим Общепринятая схема: #include stdio.h FILE *f; main() { if((f=fopen("myFile.txt", "r"))! =NULL. else. } Закрытие файла: int fclose(FILE*fp) int fcloseall(void) Переоткрытие файла с другими правами доступа: FILE *freopen(const char *Filename, const char *mode, FILE *stream) Открытие безымянного временного файла, уничтожаемого при закрытии или завершении программы: FILE *tmpfile(void) Внимание! При задании имени файла с маршрутом доступа не забывайте ставить разделитель между именами каталогов в виде двойного обратного слэша: c: \\dir1\\dir2\\Filem\\name или c: /dir1/dir2/Filem/name Стандартные потоки: stdin, stdout, stderr, stdaux, stdprn являются указателями на переменные типа FILE и могут использоваться наравне с возвращаемыми функцией fopen. Библиотеки Си содержат функции потокового посимвольного, построчного, блокового и форматированного ввода-вывода. ВВОД - ВЫВОД СИМВОЛОВ. int fgetc(FILE * stream )/* Возвращает следующий символ из файла с преобразованием в int. */ int getc(FILE *__fp); - читает символ из потока int fgetchar( void ); /* Возвращает следующий символ из stdin; это всё равно. Что fgetc (stdin). */ int getchar(void); //-из stdin int fgetchar(void); //-получает символ из stdin int ungetc(int ch, FILE *fp) - возвращает символ назад в поток int fputc(int c, FILE *stream) - вывод символа _ в файл int putc(const int c, FILE *fp) - в поток int fputchar(int c) -вывод символа в stdout int putchar (const int c) - в stdout int getch(void)-с клавиатуры без отображения(в conio.h) int putch(int c)-в текущее окно ВВОД - ВЫВОД СТРОК сhar * fgets ( char s, int n, FILE * stream ) - Читает символы из файла. Пока не наберёт n-1 или встретит символ новой строки. В конец всегда запишется нулевой байт конца строки. Возвращает указатель на строку или NULL. char * gets(char *s) - со стандартного ввода до ‘\n’ int fputs(const char *s, FILE *stream) - вывод до нуль-байта int puts(const char *s) - то же в stdout БЛОКОВЫЙ ВВОД - ВЫВОД. Чаще всего используется при переносе структурных переменных или массивов. Файл следует открывать в 2-ичном режиме, а в качестве размера блока указывать sizeof(var) int fread(void *ptr,int size,int n,FILE *fp) - чтение n элементов размером size байт каждый в буфер ptr из файла fp При ошибке возвращается EOF int getw(FILE *fp) - чтение целого из файла fp int fwrite(void *ptr,int size,int n,FILE *fp) - запись блока int putw(int w,FILE*fp) - запись целого Перечень функций форматированного ввода - вывода (их прототипы и соответствующие заголовочные файлы для подключения библиотек вы получите через help - систему интегрированной среды) int fprintf(FILE *stream, const char *format,. ) int fscanf(FILE *stream,const char *format,. ) ПРОИЗВОЛЬНЫЙ ДОСТУП К ФАЙЛАМ. Место в файле, куда ведется запись или откуда осуществляется считывание, определяется значением указателя чтения - записи. Стандартная Си - библиотека содержит подпрограммы для установки этого указателя в нужное место, т. е. позволяет доступ к любому байту в файле. void rewind(FILE *fp) - перемотка указателя в начало файла int fseek(FILE *fp, long Offset, int from_where) - сдвигает указатель на Offset байт к началу или концу файла от позиции from_where, которая может быть SEEK_SET (0) - от начала, SEEK_CUR (1) - от текущей позиции, SEEK_END (2) - от конца. long ftell(FILE *fp) - возвращает текущее значение указателя int fgetpos(FILE *fp, fpos_t *pos) - заносит в pos значение указателя чтения - записи int fsetpos(FILE*fp, const fpos_t *pos) - устанавливает указатель в позицию pos УПРАВЛЕНИЕ БУФЕРИЗАЦИЕЙ. Размер встроенного буфера Borland C++ 512 байт для регулярных файлов и 128 байт для стандартных. При выполнении подпрограмм установки указателя чтения - записи через rewind() и fseek() и при закрытии файла производится флэширование буфера - очистка для буфера ввода и перенос данных из буфера в файл при выводе. Программа может явно вызвать флэширование одного или всех буферов : int fflush(FILE *fp) int flushall(void) Библиотека языка Си имеет подпрограммы для либо полного отключения буферизации, либо задания необходимого размера буфера, либо использования в качестве буфера предоставляемую программой область памяти: void setbuf(FILE *fp, char *buf) - если buf == NULL то буферизация отключена, иначе буфер в 512 байт размещается по адресу buf. int setvbuf(FILE *fp,char *buf,int type,unsigned size) - type задает способ буферизации: _IONBF - выключена, _IOFBF - под буфер выделяется size байт по адресу buf, а если buf == NULL, то место под буфер будет в куче; _IOLBF - при каждой записи ‘\n’ буфер флэшируется. Префиксный доступ к файлам Базируется на группе подпрограмм нижнего уровня, сразу обращающихся к OS (io.h) int open(const char *pathname, int access [,unsigned mode]) - открывает файл в режиме чтения- записи и возвращает префикс открытого файла или -1; через access можно задать права доступа, а через mode режим создания файла: access: O_RDONLY, OWRONLY, O_RDWR,O_CREAT использует параметр mode: S_IFMT - маска файла (в ДОС не поддерживается), S_IFDIR - файл является каталогом, S_IFIFO,S_IFCHR - спец символьный файл, S_IFREG - регулярный O_TRUNC, O_EXCL, O_APPEND, O_TEXT, O_BINARY, O_NOINHERIT - понятны по написанию. int _open(const char * Filename, int Oflags) Значения Oflags формируются по ИЛИ из констант: FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_LABEL, FA_DIREC, FA_ARCH int _creat(const char *path, int attrib) int creat(const char *path, int amode) - эти функции создают файл int createnew(const char *path, int attrib)- отличается тем, что при наличии файла с указанным именем возвращает ошибку -1 int creattemp(char *path,int attrib) - генерирует уникальное имя и создает файл в указанном каталоге. int close(int handle), int _Close(int handle) - функции закрытия файлов int read(int handle,void *buf,unsigned len). int _read(int handle,void *buf,unsigned len) - читать len байт из файла handle в буфер buf int write(int handle,void *buf,unsigned len) int _write(int handle,void *buf,unsigned len) - запись long lseek(int handle, long Offset, int fromwhere) - установка указателя префиксным доступом Переадресация файлового ввода - вывода. В составе MS DOS есть подпрограммы для дублирования открытых файлов - вызов функции АН=45Н прерывания 21Н приводит к появлению в таблице открытых файлов 2-х копий элементов и на один и тот же файл можно будет ссылаться по 2-м разным значениям индексов элементов (префиксов). При выполнении вызова АН=46Н копирование элемента происходит в заданное место таблицы и если это место занято, т. е. заданный префикс уже выделен открытому файлу, этот файл автоматически закрывается. При дублировании изменяется только префикс файла, а все другие реквизиты (положение указателя, режим открытия) сохраняются. В Си эти вызовы отображены 2-мя библиотечными функциями: int dup(int handle) - дублирует префикс в свободное место таблицы открытых файлов; при достижении предела на число открытых файлов errno=EMFILE, при ошибке возвращается -1 и в errno=EBADF. int dup2(int old_handle,int new_handle) - выполняет вызов АН=46Н Как правило, эти функции используются при переадресации обмена со стандартными файлами ввода - вывода Создание и уничтожение файла - каталога. В ОС есть подпрограммы для создания, удаления, просмотра содержимого каталогов (директориев) в пределах текущего накопителя и эти подпрограммы дублируются в библиотеке Си с прототипами в dir.h : int mkdir(const char *path) - для создания каталога int rmdir(const char *path) - для удаления пустого каталога Управление текущим накопителем и каталогом. Во внутренних переменных ДОС хранятся номера текущего накопителя и текущего каталога для каждого накопителя. Библиотека Си содержит функции для определения и установки текущих каталога и накопителя: int getdisk(void) - возвращает номер накопителя 0 - А, 1-В. int setdisk(int drive) - устанавливает drive текущим диском int getcurdir(int drive,char *directory) - возвращает текущий каталог char *getcwd(char *buf,int buflen) - запишет в buf маршрут текущего рабочего каталога int chdir(const char *path) - установит текущим каталог Чтение содержимого каталога и поиск файлов. int findfirst(const char *Filename,struct ffblk *ffblk,int attrib) - вызывает АН=4ЕН для получения информации о первом файле, имя которого Filename и атрибут attrib; допускается использование шаблонов имен файлов. При совпадении заполняется структурная переменная по шаблону ffblk: struct ffblk{ char ff_reserved[21]; char ff_attrib; unsigned ff_time; unsigned ff_date; long ff_Size; char ff_name; }
int findnext(struct ffblk *ffblk) - продолжает поиск совпадений, начатый findfirst(). void fnmerge(char *panh,const char *drive, const char *dir, const char *name, const char *ext) - в path строится строка спецификации файла по заданным компонентам int fsplit(const char *path,char *drive, char *dir,char *name, char *ext) - разборка спецификации на элементы char *searchpath(const char *File) - выполняет поиск файла по имени и возвращает указатель на его полную спецификацию или NULL Переход от префиксной к потоковой форме доступа. (stdio.h) FILE *fdopen(int handle, char*type) - создает описание потока и возвращает указатель на него, в поле fd префикса запишется handle уже открытого файла, в type задается право доступа к файлу - оно не должно противоречить правам, заданным при префиксном открытии Удаление и переименование файлов. (stdio.h) int unlink(const char *Filename) - для удаления файла (dir.h) int rename(const char* oldname, const char *newname) - для переименования файла char *mktemp(char *template) - генерирует уникальное имя файла в шаблон template, содержащий символы, обязательно включаемые в имя char *tmpnam(char *sptr) - генерирует имя, не совпадающее ни с одним в текущем каталоге, помещает его в буфер sptr длиной 13 байт Определение существования файла или каталога. Определить существование регулярного файла можно с помощью функций открытия, задав права только для чтения, а проверку наличия каталога - попыткой установить этот каталог текущим. Другой способ определения существования файла или каталога - использование функции findfirst. Но более предпочтительным является использование функций, не выполняющих открытия файла и позволяющих получить дополнительную информацию: (io.h) int access(const char *Filename, int amode) - проверяет существование или права доступа, параметр amode: 00 - проверка существования файла или каталога 02 - допускается ли запись 04 - допускается ли чтение 06 - проверка на чтение - запись При утвердительном ответе возвращается 0, иначе -1 Определение и установка параметров файла. Полезная информация о файле может быть получена функциями fstat и stat - они заполняют поля структурной переменной по шаблону, описанному в заголовочном файле sys\stat.h : struct stat{ short st_dev; номер накопителя short st_ino; short st_mode; биты прав доступа short st_nlink; число привязок к файлу в MS DOS =1 int st_uid; int st_gid; short st_rdev; то же что и st_dev long st_Size; размер открытого файла long st_atime; } (sys\stat.h) int fstat(int handle, struct stat *statbuf) int stat(char *path,struct stat *statbuf) Наиболее часто обращаются к этим функциям для определения размера файла или прав доступа. Другой способ получения длины файла - позиционирование указателя на конец файла (можно сразу открыть его для дополнения а+) и получение его позиции. При префиксном доступе можно изменить длину файла функцией: int chsize(int t handle,long size) - усекает или расширяет файл Для получения некоторых параметров состояния открытого потока можно использовать функции (stdio.h): int feof(FILE *stream) - возвращает не 0, если достигнут конец файла int ferror(FILE *strem) - не 0 при ошибках int clearerr(FILE *fp) - сброс индикаторов ошибки и конца файла Для префиксных файлов (io.h): int eof(int handle) - 1 если конец файла Изменение прав доступа к файлу может быть выполнено функциями: (sys/stat.h) int chmod(const char *Filename,int amode) - изменение прав доступа (атрибута) int _chmod(const char *Filename,int func, [,int attrib]) - позволяет либо запросить (func=0), либо установить (func=1) права доступа (io.h) int setmode(int handle,int amode) - устанавливает права доступа, amode либо O_TEXT, либо O_BYNARY ПОЛУЧЕНИЕ И УСТАНОВКА ДАТЫ И ВРЕМЕНИ (io.h) int getftime(int handle,struct ftime *ftimep) int setftime(int handle, struct ftime *ftimep)
Задания 1. Дан текстовый файл. Считать содержимое файла на экран, задерживая текст на экране до нажатия клавиши при полном заполнении экрана. 2. Дан текстовый файл, содержащий информацию о книгах в библиотеке: Автор, название, издательство, год издания. Составить программу, позволяющую находить информацию о всех книгах: заданного автора, названия, издательства или года издания, сортировать список книг в файле по какому-либо признаку. 3. Дан файл, содержащий сведения о студентах. Информация о каждом студенте включает: ? фамилию; ? имя; ? отчество; ? дату рождения; ? шифр группы; ? оценки за последнюю сессию. Составить программу, которая позволяет работать в нескольких режимах: - создавать новый файл с информацией и заполнять его; - дополнять существующий файл; - удалять записи из файла; - просматривать записи по порядку; - получать информацию о студентах, имеющих средний балл сессии больше заданного (результат получать на экране и в файле).