- •( Stream – поток, I - input , o – output)
- •Иерархия потоковых классов (одна ветвь)
- •Стандартные потоки ввода – вывода
- •1) Для целых чисел, 2) для вещественных чисел и 3) для строк
- •Компонентные функции класса ios для форматирования
- •Манипуляторы с параметрами ( определены в файле iomanip.H )
- •Ввод-вывод для типов, определенных пользователем
- •Функции чтения
- •Работа с файлами
- •Ввод-вывод нижнего уровня
- •Текстовой и бинарный файлы
- •Открытие и закрытие файлов
- •Чтение и запись данных
- •Int fd ; // дескриптор файла
Открытие и закрытие файлов
int open (const char *path , int mode); // прототип в файле < io.h >
int fd=open( имя файла, флаги); // вызов функции
Первый параметр задает имя файла
Параметр mode определяет режим открытия файла, представляет результат битовой дизъюнкции флагов обмена, определенных в файлах <sys\stat.h> или
fcntl.h:
O_APPEN – открыть для дополнения;
O_BINARY – открыть в бинарном режиме;
O_CREAT – создать и открыть новый файл;
O_EXCL – в сочетании с O_CREAT создает только новый файл , если
файл существует, он не стирается , выводится сообщение об
ошибке;
O_RONLY – открыть только для чтения;
O_RDWR – открыть и для чтения и для записи;
O_TEXT – открыть в текстовом режиме;
O_TRUNC - открыть существующий файл и стереть его содержимое;
O_WRONLY- открыть только для записи.
Режим открытия должен устанавливаться явно , т.к. умолчания нет.
Вызов функции creat ( ) эквивалентен вызову:
open( имя файла ,O_CREAT|O_TRUNC|O_WRONLY).
Для закрытия файлов функция:
int close( дескриптор файла)
Возвращает 0 при успешном закрытии и -1 в случае ошибки.
Чтение и запись данных
int read( int fd, char* buffer, unsigned int count)
– читает count байт из файла, с дескриптором fd в буфер buffer.
Возвращает число байт, помещенных в буфер;
0 – при достижении конца файла; - 1 – при возникновении ошибки чтения.
Чтение идет с текущей позиции в файле. В текстовом режиме идет преобразование двух символов к одному ‘\n’ и в возвращаемом значении вместо двух символов учитывается один.
int write( int fd, char* buffer, unsigned int cout)
- записывает count байт из буфера buffer в файл, открытый с дескриптором fd .
Запись идет с текущей позиции. Возвращает количество реально записанных байтов, в текстовом режиме это количество будет превышать количество реально записанных байтов за счет преобразования ‘\n’ в CR и LF.
Возвращает –1 при ошибке записи ( напр. нет места на диске).
Копирование файла
…
void main()
{ int fdin , fdout, n ;
char buf[512]; // размер стандартного буфера – размер кластера
if( fdin =open(“f1.dat” , O_RDONLY) = = -1) {cout<<”Ошибка 1”; exit(1);}
if( fdout =open(“f2.dat” , O_WRONLY|O_CREAT|O_TRUNC) = = -1) {cout<<”Ошибка 2”; exit(1);}
while (n=read(fdin, buf , 512)>0)
write( fdout, buf, n);
}
Произвольный доступ к файлу
При необходимости файл можно читать не последовательно, а в произвольном порядке. Функция для изменения текущей позиции чтения/ записи в файле:
long lseek( int fd, long offset, int origin)
Изменяет позицию в файле с дескриптором fd относительно origin на offset байт.
Параметр origin задает точку отчета:
SEEK_SET = = 0 - начало файла
SEEK_CUR = = 1 - текущая позиция
SEEK_END = = 2 – конец файла.
Возвращает новую позицию в файле от начала, от нуля.
lseek( fd, 0L, SEEK_SET); -установка на начало
lseek( fd, 0L, SEEK_END); -установка на конец файла
Функция определяющая текущую позицию в файле
long tell( int fd);
…
read(fd, buf, sizeof ( запись) ) ;
lseek( fd , - sizeof ( запись) ,SEEK_CUR);
…
write( fd, buf, sizeof(запись) ) ;…
Полезные функции:
Как правило, параметру для дескриптора файла во всей литературе дают имя handle
1) long filelength ( int handle);
-
возвращает длину файла связанного с дескриптором handle в байтах.
… int n = filelength(fd) / sizeof(запись); … //количество записей в файле
2) int chsize ( int handle, long size );
-
изменяет длину файла , связанного с handle – усекает его или расширяет в зависимости от соотношения между size и первоначальной длины файла, size новая длина файла. При расширении новое место заполняется символами \0.
Возвращает 0 , если изменение прошло успешно и –1 , если нет.
3) int remove ( const char*filename ) ;
- уничтожает существующий на диске файл с именем filename, который перед удалением должен быть закрыт.
Возвращает 0 , если удаление прошло успешно и –1 , если нет.
4) int rename ( const char*oldname , const char*newname )
- переименование существующего файла с именем oldname, который перед переименованием должен быть закрыт.
Новое имя newname должно быть оригинально на диске.
Возвращает 0 , если переименование прошло успешно и –1 -, если нет.
Потоковый ввод- вывод на базе библиотеки классов
Рассмотрим механизмы выполнения основных работ с файлами на базе связи файлов с потоками ввода-вывода.
Основные виды работ с файлами
-
создание файла;
-
создание потока;
-
открытие файла;
-
присоединение файла к потоку
-
обмены с файлом с помощью потока
-
отсоединение потока от файла
-
закрытие файла
Создание потоков
Потоки для работы с файлами – объекты следующих классов:
ofstream - для записи данных в файл
ifstream - для чтения данных из файла
fstream - для чтения и записи данных
Описание этих классов находится в файле < fstream.h>
Определение потоков - объектов классов
( первый способ – создание объекта с помощью конструктора по умолчанию)
ofstream Fout //выходной файловый поток
ifstream Fin //входной файловый поток
fstream Fio //входной выходной файловый поток
При таком создании под объекты выделяется память – это буфер обмена и инициируются переменные, характеризующие состояние потока
Т. к. классы файловых потоков являются производными классами от классов стандартных входных и выходных потоков и от класса ios , то они наследуют все переменные и флаги состояния потока , а также компонентные функции, выполняющие форматированный и не форматированный обмен , которые мы рассмотрели выше.
Создав файловый поток, нужно присоединить его к конкретному файлу с помощью компонентной функции open ().
Эта функция открывает файл ( если он существует) или создает новый файл и связывает его с потоком
void open (const char* filename, int mode= умалчиваемые значения,
int protection= умалчиваемые значения)
Первый параметр – имя файла.
Второй - дизъюнкция флагов , определяющих режим работы с файлом
ios:: in = 0x01 // открыть только для чтения
ios:: out = 0x02 // открыть только для записи
ios:: ate = 0x04 // при открытии искать конец файла
ios:: app = 0x08 // дописывать данные в конец файла
ios::trunc= 0x10 //вместо существующего создать новый файл
ios::nocreate=0x20 //не открывать новый файл, (ошибка, если файл не
существует)
ios::noreplace=0x40 // не открывать существующий файл
ios::binary = 0x80 // открыть для двоичного обмена
Умалчиваемое значение параметра mode для потока класса ifstream равно
ios::in для потока класса ofstream равно ios::out.
Для третьего параметра, определяющего защиту, используется умалчиваемое значение, которое всегда устраивает пользователя.
Вызов компонентной функции осуществляется с помощью уточненного имени:
Имя объекта . вызов компонентной функции
Имя потока. open( имя файла, режим , защита)
Fout. open( “ D:\\ DATA\\work.dat» ) // по умолчанию ios::out, если файл не существует, он будет создан и присоединен к потоку Fout.
Применяя к потоку операцию включения Fout << …
или вызывая компонентные функции Fout.put(‘…’) или Fout.write(…) , запись будет производиться в файл.
Fin.open(«result.txt» ) // по умолчанию ios::in, если файл не существует, то вызов функции приведет к ошибке. Существующий файл присоединяется к потоку Fin.
Применяя операцию извлечения Fin>>…, или вызывая компонентные функции Fin.get(…) , Fin. getline(…), Fin.read(…)можно читать из файла
Fio.open(«change.dat», ios::out) // файл открыт для записи и будет иметь такую направленность до закрытия, потом его можно вновь открыть для считывания.
Для проверки удачности завершения open( ) существует перегруженная для классов потоков операция ! . Если ошибок не было , то ! имя потока выражение имеет нулевое значение, противном случае не нулевое.
(Если !поток равно нулю, то все хорошо, т.е. поток не должен быть нулевым)
…
if( ! Fin) { cout<< «ошибка при открытии файла»<<endl; exit(1);}
Закрытие файла
имя файлового потока(присоединенного к файлу). close()
Чтобы изменить режим доступа к файлу, его надо закрыть и открыть вновь в нужном режиме.
Присоединение к потоку , используя дескриптор файла
Если файл был открыт с помощью функции creat( ), то для присоединения к файловому потоку можно использовать компонентную функцию attach ( ), доставшуюся по наследству от базовых классов. Эта функция имеет параметром дескриптор открытого файла
… int descrip= creat ( «имя_файла», S_WRITE);
… ofstream Fout ; //определение потока
Fout.attach ( descript);// присоединение файла с дескриптором descript к
//потоку Fout
if(!Fout) { cerr<<»ошибка присоединения файла» ; exit(1) }
Определение потоков - объектов классов с присоединением потока к физическому файлу
(второй способ – создание объекта с помощью конструктора с параметрами)
Первый параметр конструктора – имя физического файла, второй -мода.
ifstream input (« filename.ext», ios::in )
ofstream output(« filename.out», ios::out)
fstream ioput (« …» ,ios:: out)
После можно писать в файл и читать из файла
input.read ( buffer , number_of_buffer )
output.write( buffer , number_of_buffer )
Эти функции возвращают ссылку на поток, поэтому их можно выполнять цепочкой.
Удобно использовать компонентную функцию этих классов
int eof( )
Возвращает ненулевое значение, имеет место условие конца файла.
Перегрузка операций ввода – вывода
Пример функции записи в текстовой файл ( напр. создание файла данных)
и чтения из текстового файла.
#include <fstream.h>
#include <iomanip.h>
ofstream fout;
ifstream fin;
struct st
{ char name [20]; long sh, cen;}zap[3]={ {"yy yyy", 1745,186},
{"oooo", 1234,78},
{"ddddddddd", 3421,96}};
//перегрузка
ofstream & operator << (ofstream& out , st zap2)
{ out <<setw(9)<<zap2.name <<" " <<zap2.sh<<" " << zap2.cen << "\n" ;
return (out);}
ifstream& operator >> (ifstream& fin , st& zap)
{ char ch[5];
fin.getline(zap.name,10); fin >> zap.sh >> zap.cen;
fin.getline(ch,5,'\n');
return fin;}
struct st zap1;
void main()
{
fout.open( "\\myf");
for(int i=0; i< 3; i++)
fout<<zap[i] ;
fout.close();
fin.open("\\myf") ;
лев. выр. 10сс призн. сс .0 +
//cout << cout.setf(0x0002|0x0010|0x0080|0x0200|0x0400) ;
16сс
//cout << cout.setf(0x0002|0x0040|0x0080|0x0200) ;
for(int i=0 ; i<3 ; i++)
{fin>> zap1;
cout <<"\n"<< zap1.name << setw(15)<<zap1.sh <<setw(15)<<zap1.cen<<"\n"; }
fin.close();
}
/*
// запись и считывание в режиме бинарного обмена с использованием
перегруженных операций << и >>
#include <fstream.h>
#include <iostream.h>
#include <iomanip.h>
ofstream fout;
ifstream fin;
struct st
{ char name [20]; long sh,cen;}zap[3]={ {"yy yyy", 1745,186},
{"oooo", 1234,78},
{"ddddddddd",3421,96}};
ofstream & operator << (ofstream& out , struct st zap2)
{ out <<zap2.name<<’ ’<<zap2.sh<<" " <<zap2.cen<<" ";
return (out);}
ifstream& operator >> (ifstream& fin , struct st& zap)
{ fin.getline(zap.name,20,'\0'); fin >> zap.sh >> zap.cen;
return fin;}
struct st zap1;
void main()
{
fout.open( "\\myf",0x80);
for(int i=0; i< 3; i++)
fout<<zap[i] ;
fout.close();
fin.open("\\myf",0x80) ;
for(int i=0 ; i<3 ; i++)
{ fin>> zap1;
cout <<setw(10)<< zap1.name << " "<<zap1.sh <<" "<<zap1.cen<<"\n";}
fin.close();
}
*/
//запись и чтение файла с помощью функций read и write
#include <fstream.h>
#include <iostream.h>
ofstream fout;
ifstream fin;
struct st { char* name; char* FIO ; long sh, cen;}zap1,zap={ "rrrrr rrrrr",
"fff ff",1745,186};
void main()
{ st*p = &zap;
char *ss = (char*)p ;
fout.open( "\\myf",0x80);
fout.write(ss, sizeof(st)) ;
fout.close();
fin.open("\\myf",ios::in|0x80) ;
fin.read((char*)&zap1,sizeof(st));
fin.close();
cout << zap1.name<<"\n"<<zap1.FIO<<"\n"<<zap1.sh<<"\n" <<zap1.cen;
}
Библиотека ввода-вывода Си ( stdio.h)
Рассмотрим функции обмена верхнего уровня, которые обеспечивают
буферизацию данных при обмене с файлом.
Функции реализуют обмен с потоком-источником или приемником последовательности байт(в бинарном режиме) или последовательности строк (в текстовом режиме обмена)
Открытие файла
Объявляется указатель на структуру типа FILE, в которой должна будет содержаться информация о файле. Тип FILE определен в файле stdio.h
typedef struct
{shot level; // уровень буфера
unsigned flags ; // флаг статуса файла