Файл – это именованная область внешней памяти. Файл имеет следующие характерные особенности:
имеет имя на диске, что дает возможность программам работать с несколькими файлами;
длина файла ограничивается только емкостью диска.
Особенностью С является отсутствие в этом языке структурированных файлов. Все файлы рассматриваются как не структурированная последовательность байтов.
Библиотека С поддерживает три уровня ввода-вывода:
- потоковый ввод-вывод;
- ввод-вывод нижнего уровня;
- ввод-вывод для консоли портов (зависит от конкретной ОС).
На уровне потокового ввода-вывода обмен данными производится побайтно.
При вводе с диска или при считывании из файла данные помещаются в буфер ОС, а затем побайтно или порциями передаются программе пользователя.
При выводе в файл данные также накапливаются в буфере, а при заполнении буфера записываются в виде единого блока на диск. Буферы ОС реализуются в виде участков основной памяти.
Поток – это файл вместе с предоставленными средствами буферизации.
Функции библиотеки С, поддерживающие обмен данными на уровне потока позволяют обрабатывать данные различных размеров и форматов. При работе с потоком можно:
Открывать и закрывать потоки (при этом указатели на поток связываются с конкретными файлами);
Вводить и выводить строки, символы, форматированные данные, порции данных произвольной длины;
Управлять буферизацией потока и размером буфера;
Получать и устанавливать указатель текущей позиции в файле.
Прототипы функций ввода-вывода находятся в заголовочном файле <stdio.h>, который также содержит определения констант, типов и структур, необходимых для обмена с потоком.
Прежде, чем начать работать с потоком, его надо инициировать, т. е. открыть.
При этом поток связывается со структурой предопределенного типа FILE, определение которой находится в файле <stdio.h>.
В структуре находится указатель на буфер, указатель на текущую позицию и т. п.
При открытии потока возвращается указатель на поток, т. е. на объект типа FILE.
Указатель на поток должен быть объявлен следующим образом:
- include <stdio.h>
. . . . . . . .
A. *f; //указатель на поток
Указатель на поток приобретает значение в результате выполнения функции открытия потока:
FILE* f open(const char*filename, const char*mode);
где const char*filename – строка, которая содержит имя файла, связанного с потоком,
- char*mode – строка режимов открытия файла.
Например: - f=fopen("t.txt","r");
где t.txt – имя файла, r – режим открытия файла.
Файл, связанный с потоком, можно открыть в одном из 6 режимов
Режим |
Описание режима открытия файла |
r |
Файл открывается для чтения, если файл не существует , то выдается ошибка при исполнении программы. |
w |
Файл открывается для записи, если файл не существует, то он будет создан, если файл уже существует, то вся информация из него стирается. |
Файл открывается для добавления, если файл не существует, то он будет создан, если существует, то информация из него не стирается, можно выполнять запись в конец файла |
|
r+ |
Файл открывается для чтения и записи, изменить размер файла нельзя, если файл не существует , то выдается ошибка при исполнении программы. |
w+ |
Файл открывается для чтения и записи, если файл не существует, то он будет создан, если файл уже существует, то вся информация из него стирается. |
a+ |
Файл открывается для чтения и записи, если фай не существует, то он будет создан, если существует, то информация из него не стирается, можно выполнять запись в конец файла |
Поток можно открывать в текстовом (t) или двоичном режиме(b). В текстовом режиме поток рассматривается как совокупность строк, в конце каждой строки находится управляющий символ ‘\n’. В двоичном режиме поток рассматривается как набор двоичной информации. Текстовый режим устанавливается по умолчанию.
В файле stdio.h определена константа EOF, которая сообщает об окончании файла (отрицательное целое число).
При открытии потока могут возникать следующие ошибки:
- файл, связанный с потоком не найден (при чтении из файла);
- диск заполнен (при записи);
- диск защищен от записи (при записи) и т. п.
В этих случаях указатель на поток приобретет значение NULL (0). Указатель на поток, отличный от аварийного не равен 0.
После того как файл открыт, в него можно записывать информацию или считывать информацию, в зависимости от режима.
Открытые файлы после окончания работы рекомендуется закрыть явно. Для этого используется функция:
int f close(FILE*f);
Изменить режим работы с файлом можно только после закрытия файла.
Для текстового файла:
if(f=fopen(filename,”rt”)==0)//открываем для чтения и проверяем возникает ли ошибка при открытии файла.
Для вывода об ошибке при открытии потока используется стандартная библиотечная функция из файла <stdio.h>
void perror (const char*s);
Эта функция выводит строку символов, на которую указывает указатель s, за этой строкой размещается двоеточие пробел и сообщение об ошибке. Текст сообщения выбирается на основании номера ошибки. Номер ошибки заносится в переменную int errno(определена в заголовочном файле errno.h).
Для символьного ввода-вывода используются функции:
int fgetc(FILE*fp),
где fp – указатель на поток, из которого выполняется считывание. Функция возвращает очередной символ в форме int из потока fp. Если символ не может быть прочитан, то возвращается значение EOF.
int fputc(int c, FILE*fp),
где fp – указатель на поток, в который выполняется запись, c – переменная типа int, в которой содержится записываемый в поток символ. Функция возвращает записанный в поток fp символ в форме int . Если символ не может быть записан, то возвращается значение EOF.
Пример:
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
void main()
/**
FILE *f;
char c;
char *filename=”f.txt”;
if((f=fopen(filename,”r”)==0)
/**
perror(filename);exit(0);
**/
while(c=fgetc(f)!=EOF)
putchar(c); //вывод с на стандартное устройство вывода
fclose(f);
**/
Для построчного ввода-вывода используются следующие функции:
char* fgets(char* s,int n,FILE* f),
где char* s – адрес, по которому размещаются считанные байты,
int n – количество считанных байтов,
FILE* f – указатель на файл, из которого производится считывание.
int puts(char* s, FILE* f),
где char* s – адрес, из которого берутся записываемые в файл байты,
FILE* f – указатель на файл, в который производится запись.
Пример:
//копирование файла in в файл out
int MAXLINE=255;
FILE *in, *out;
char* buf[MAXLINE]; in=fopen(“f1.txt”,”r”); out=fopen(“f2.txt”,”w”); while(fgets(buf,MAXLINE,in)!=0)
fputs(buf,out);
fclose(in);
fclose(out);
void del(char *filename)
/**
//удаление записи с номером х
FILE *f, *temp;
f=fopen(filename,”rb”); //открыть исходный файл для чтения
temp=fopen(“temp”,”wb”) //открыть вспомогательный файл для записи
student a;
for (long i=0;fread(&a,sizeof(student),1,f); i++)
if(i!=x)
/** fwrite(&a,sizeof(student)1,temp); **/
else
/** cout<<a<<" - is deleting..."; **/
fclose(f); fclose(temp);
remove(filename);
rename(“temp”, filename); **/
void add(char *filename)
/**
//добавление в файл
student a;
int n;
f=fopen(filename,”ab”)открыть файл для добавления
cout<<"\nHow many records would you add to file?";
cin>>n;
for(int i=0;i<n;i++)
/**
прочитать объект
fwrite(&a,sizeof(student),1,f);//записать в файл
**/
fclose(f);//закрыть файл
**/