Зарегистрироваться
Восстановить пароль
FAQ по входу

Работа с файлами

  • Добавлен пользователем , дата добавления неизвестна
  • Отредактирован
Работа с файлами
Лабораторная работа №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. Дан файл, содержащий сведения о студентах. Информация о каждом студенте включает:
фамилию;
имя;
отчество;
дату рождения;
шифр группы;
оценки за последнюю сессию.
Составить программу, которая позволяет работать в нескольких режимах:
- создавать новый файл с информацией и заполнять его;
- дополнять существующий файл;
- удалять записи из файла;
- просматривать записи по порядку;
- получать информацию о студентах, имеющих средний балл сессии больше заданного (результат получать на экране и в файле).
  • Чтобы скачать этот файл зарегистрируйтесь и/или войдите на сайт используя форму сверху.
  • Регистрация