ООП. Пособие по ООП в С++. Создание сложных программных систем Объектно ориентированная технология
Скачать 2.1 Mb.
|
14.7.10 Методы неформатированного вывода класса ofstream flush() Принудительный вывод в поток данных буфера вывода. Примечание. При записи данные переписываются в файл только при наполнении буфера. put( c ) Вывод символа в потток Пример применения метода ignore() Пропустить первые две строки в текстовом файле Файл D.txt содержит данные 101 Text * -3.14 102 Text * -3.14 103 Text * -3.14 104 Text * -3.14 105 Text * -3.14 Int main() { ifstream iif( "D.txt" ); if (!(iif)) { cout<< "No open file" ; return 1; } // Пропуск двух првых строк for ( int i=1;i<=2;i++) iif.ignore(20, '\n' ); char str1[20]; iif.getline(str1,20, '\n' ); //продолжение чтения файла while (!iif.eof()) { iif.getline(str1,20, '\n' ); cout< 0; } Пример применения метода flush ofstream iif( "D.txt" ); if ((iif)) { cout<< "No open file" ; return 1; } char str1[20]= "106 Text * 100" ; iif< 1. Числовые данные должны быть разделены пробелом или символом \n. 2. Символы должны следовать последовательно друг за другом. 3. Если в одной строке подготовлены данные числовые, символьные, строковые (это смешанный ввод), то нужно помнить, о разделителях между данными. Потоковый ввод >> читает данные до пробела, поэтому для чисел это хорошо. Пример на чтение числовых данных из текстового данных В текстовом файле хранится N чисел. На первой строке хранится число- N количество чисел в файле. Со второй строки расположены N чсел по несколько чисел на строке, по сколько не знаем. Записать прочитанные данные в массив из N чисел. Пример содержимого файла: 11 1 2 3 4 5 6 7 8 9 10 ifstream fin( "C.txt" ); if (!fin) { cout<< "No open file" ; return 1; } int N; fin>>N; int *x= new int [N],i=0; while (!fin.eof())//до конца файла fin { fin>>x[i];i++; } fin.close(); for ( int i=0;i ; fin.clse(); Пример чтения данных разного типа подготовленных в одной строке и таких строк несколько. Пусть в файле С.txt на нескольких строках подготовлены данные: 101 Текст * -3.14 102 Текст * -3.14 103 Текст * -3.14 ifstream fin( "C.txt" ); if (!fin) { cout<< "No open file" ; return 1; } int N; string str; char ch; double x; while (!fin.eof())//до конца файла fin { fin>>N; fin>>str; fin>>ch; fin>>x; cout< < < < 0; } 14.7.11 Пример. Операции с текстовым файлом. #include "stdafx.h" #include "fstream" #include "iostream" using namespace std; //создание текстового файла //Структура файла: в строке одно число, //строка завершается символом конца строки void inpfiletxt(ofstream &fout, char *namefile) { fout.open(namefile,ios::out|ios::trunc); for ( int x=1;x<=10;x++) { fout< fout.close(); } //вывод содержимого текстового файла //чтение числа и символа конца строки //чтобы обработать до конца файла void outfiletxt( char *namefile) { int x; ifstream fin; cout< { fin>>x; fin.get(); cout< } //добавление записи в конец файла void appfiletxt(ofstream &fout, char *namefile, int x) { fout.open(namefile,ios::out|ios::app); fout< //прочитать запись по заданному номеру void seekNtextfile( char *namefile, int n) { int x; ifstream fin; fin.open(namefile,ios::in); int i; for (i=1;(i } cout< while (!fin.eof()&& (i==n)) { fin>>x; fin.get(); cout< } int _tmain( int argc, _TCHAR* argv[]) { ofstream fout; inpfiletxt(fout, "A.txt" ); ifstream fin; outfiletxt( "A.txt" ); appfiletxt(fout, "A.txt" ,100); outfiletxt( "A.txt" ); seekNtextfile( "A.txt" ,4); cin.get(); return 0; } 14.8 Двоичные файлы Используются для более компактного хранения информации. Хранят данные в машинном формате, т.е. в том виде как они представлены в оперативной памяти. Например, значение вещественной переменной типа float будет записано в файл в формате с плавающей точкой. Под это значение будет отведено столько байт, сколько требуется переменной формата float. Логически файл состоит из записей фиксированной длины, минимальная длина один байт, максимальная соответствует размеру записанной при создании файла записи. Поэтому из такого файла удобно читать записи: каким форматом записали, таким и читать будем. Создается файл программным путем. Как и текстовый файл имеет последовательную организацию, т.е. новые записи добавляются в конец файла. Обрабатывается файл так же последовательно от первой записи до последней. Для двоичных файлов с записями фиксированной длины применяется метод произвольного доступа, при котором можно обрабатывать отдельную запись: прочитать, изменить и записать на старое место. Для применения в программе двоичного файла необходимо определить поток, поддерживающий двоичные операции. 14.8.1 Создание потока для двоичного файла 1. Создание потока для создания двоичного файла 1.1. Без связывания с физическим файлом. ofstream fb; fb.open(“data.dat”,ios::out|ios::binary); Выделенные параметры режима открытия файла обязательны для создания двоичного потока. Параметр ios::out – открытие потока для записи в файл. Параметр ios::binary – открытие двоичного потока 1.2. Связывание открытие файла при объявлении ifstream fb(“data.dat”,ios::in|ios::binary); 2. Создание потока для чтения данных из двоичного файла 2.1. Без связывания с физическим файлом. ofstream fb; fb.open(“data.dat”,ios::in|ios::binary); 2.2. Связывание открытие файла при объявлении ifstream fb(“data.dat”,ios::in|ios::binary); 3. Создание потока для добавления данных в двоичный файл 3.1. Без связывания с физическим файлом. ofstream fb; fb.open(“data.dat”,ios::in|ios::binary|ios::app); 3.2. Связывание открытие файла при объявлении ifstream fb(“data.dat”,ios::in|ios::binary|ios::app); 14.8.2 Организация записи данных в двоичный файл Запись данных в двоичный файл обеспечивает метод write Формат метода ostream& write(const char *buf, streamsize num); buf – указатель на блок памяти, значение которого будет записываться в файл. num – количество байт в блоке памяти, на который указывает buf. Хотя buf представлена в функции как char *, можно записывать в файл данные любого типа. Просто надо указатель на данные привести к char * и указать нужную длину блока в байтах. Формат двоичного файла Запись 1 Запись 2 Запись 3 Запись 4 Запись N Записи это блоки размера num. Они ничем не отделяются друг от друга. Пример создания файла с 10 записями типа double int main() { fout.open( "DD.dat" ,ios::binary|ios::trunc); if (!fout) { cout<< "No open file" ; return 1; } double val; for(int i=1; i<=10; i++) { fout.write(( char *) &val, sizeof ( double )); } fout.close(); return 0; } Пример создания двоичного файла из записей - массивов int main() { fout.open( "DD.dat" ,ios::binary|ios::trunc); if(!fout) { cout<< "file not open" ; return 1; } int x[3]={1,2,3}; //пишем массив из трех чисел fout.write(( char *) x, 3* sizeof ( int )); int y[3]={5,6,7}; fout.write(( char *) y, 3* sizeof ( int )); if (!fout.good())//контроль ошибок ввода-вывода { cout<< "Error vvoda" ; return 1; } fout.close(); ifstream fio( "DD.dat" ,ios::in|ios::binary);//открыли для чтения while (!fio.eof()) { //читаем массив из трех чисел fio.read(( char *)x, 3* sizeof ( int )); for ( int i=0; i<3;i++) cout< "DD.dat" ,ios::in|ios::binary); while (!fii.eof()) { //читаем по одному числу fii.read(( char *)&a, sizeof ( int )); cout<} return 0; } Пример создания файла из записей (или свойств полей объекта) В текстовом файле хранятся данные о книгах фонда библиотеки Структура записи о книге: struct book { char Fam[30]; char Name[15]; int year; }; Сформировать двоичный файл из записей текстового файла, в котором построчно хранятся данные: Шилдт С++ Методики 2015 Страуструп Язык С++ 2015 Иванова Г.И. ООП 2012 #include "stdafx.h" #include "fstream" #include "iostream" #include "istream" #include { char Fam[30]; char Name[15]; int year; }; //чтение из текстового файла записи типа book, формирование и запись в двоичный //функция записи в файл значения типа book void create_bin_file(ifstream &ft,ofstream &fb) { book x; while (!ft.eof()) { getline(ft,x.Fam); //заполнение Х getline(ft,x.Name); ft>>x.year; ft.get(); //Запись Х в дв.файл fb.write(( char *)&x, sizeof (book)); } ft.close(); fb.close(); } //вывод записей двоичного файла void out_bin_file(ifstream &fb) { book x; //чтение из файла всей записи fb.read(( char *)&x, sizeof (book)); while (!fb.eof()) { cout< fb.read(( char *)&x, sizeof (book)); } fb.close(); } int main() { ifstream ft; ofstream fb; char fnameText[30],fnameBin[30]; cout<< "Name for Text" ; cin>>fnameText; cout<< "Name for Text" ; cin>>fnameBin; ft.open(fnameText,ios::out); fb.open(fnameBin,ios::out|ios::binary); if (!ft || !fb) { cout<< "файл не открыт" ; return 1; } create_bin_file(ft,fb); ifstream fbb(fnameBin,ios::in|ios::binary); out_bin_file(fbb); return 0; } Пример добавления новой записи в конец двоичного файла #include "stdafx.h" #include "fstream" #include "iostream" #include "istream" #include { string Fam; string Name; int year; }; //вывод записей двоичного файла void out_bin_file(ifstream &fb) { book x; //чтение из файла всей запис сразу fb.read(( char *)&x, sizeof (book)); while (!fb.eof()) { cout< *)&x, sizeof (book)); } fb.close(); } void add_bin_file( char *fnameBin) { book x; ofstream fadd(fnameBin,ios::in|ios::binary| ios::app); cin>>x.Fam; cin>>x.Name; cin>>x.year; fadd.write(( char *)&x, sizeof (book)); fadd.close(); } int main() { char fnameText[30],fnameBin[30]; cout<< "Name for Text" ; cin>>fnameBin; fb.open(fnameBin,ios::in|ios::binary); if (!fb) { cout<< "файл не открыт" ; return 1; } out_bin_file(fb); add_bin_file(fnameBin); out_bin_file(fb); } return 0; } 14.8.3 Чтение данных из двоичного файла Из двоичного файла можно читать данные блоками по несколько байт. Размер блока должен быть к моменту чтения определен. Определение потока с операциями чтения данных двоичного файла - это объект типа ofstream. Чтение данных из двоичного файла выполняет метод класса istream. Формат метода read( istream& read(char *buf, streamsize num); buf – указатель на блок памяти (как массив), в котором будет сохранено прочитанное из файла значение в размере num. num – количество байт – размер прочитанного блока. Значение пред загрузкой в buf может быть приведено к этому типу char *. Пример чтения двоичного файла, содержащего записи о книге При создании файла с записями о книгах, записывали записи фиксированной длины – размер структуры. Чтение будем выполнять такими же блоками, в переменную типа book. Так как размер записи в файле равен размеру переменной типа book, то при чтении записи значения полей разместятся в соответствующих полях переменной. #include "stdafx.h" #include "fstream" #include "iostream" #include "istream" #include { string Fam; string Name; int year; }; void create_bin_file(ifstream &ft,ofstream &fb) { book x; while (!ft.eof()) { getline(ft,x.Fam); getline(ft,x.Name); ft>>x.year; ft.get(); fb.write(( char *)&x, sizeof (book)); fb.clear(); } ft.close(); fb.close(); } void out_bin_file(ifstream &fb) { book x; fb.read(( char *)&x, sizeof (book)); while (!fb.eof()) { cout< *)&x, sizeof (book)); } fb.close(); } void add_bin_file( char *fnameBin) { book x; ofstream fadd(fnameBin,ios::in|ios::binary|ios::app); cin>>x.Fam; cin>>x.Name; cin>>x.year; fadd.write(( char *)&x, sizeof (book)); fadd.close(); } int main() { ifstream ft; ofstream fb; char fnameText[30],fnameBin[30]; cout<< "Name for Text" ; cin>>fnameText; cout<< "Name for Text" ; cin>>fnameBin; ft.open(fnameText,ios::out); fb.open(fnameBin,ios::out|ios::binary); ifstream fbb(fnameBin,ios::in|ios::binary); if (!ft || !fb) { cout<< "файл не открыт" ; return 1; } int num; while (1) { cout<< " Operation for files" < < < < < ; cin>>num; switch (num) { case 1:create_bin_file(ft,fb); break ; case 2: {ifstream fbb(fnameBin,ios::in|ios::binary);out_bin_file(fbb); break ;} case 3:add_bin_file(fnameBin); break ; case 4:exit(0); } If(!fbb.good()) { сout<<”Ошибка ввода”< } return 0; } 14.8.4 Закрытие файла Аналогично текстовым 1) При выполнени деструктора 2) При вызве метода close 14.8.5 Методы контроля ошибок потока Метод bool good() Если флаги ошибок не установлены, то результат true. 14.9 Поток класса fstream 14.9.1 Использование одного потока для чтения и записи данных в файл Позволяет открывать файлы для операций чтения и записи. Это требуется если необходимо модифицировать записи файла. Особенно этот поток удобен для обработки файлов с записями фиксированной длины, так как позволяет изменить запись, не переписывая весь файл. Например, чтобы изменить значение поля year в файле BOOKS.txt, необходимо создать другой файл, переписать в него все записи до нужной, прочитать, изменить нужную и записать ее в новый файл, а далее переписать все остальные. Этот поток предоставляет возможность заменить данные в файле значений при последовательном проходе по файлу. При чтении и записи могут использоваться методы: put(), get(), read(), write(). Для некоторых компиляторов вывод в файл можно выполнить используя метод flush(), который перепишет данные, размещенные в буфере файла в файл, замещая находящиеся там значения. Для некоторых компиляторов нужно использовать методы seekg() или seekp(). Пример. Запись и чтение данных из файла, открыв его один раз для операций ввода и вывода. Создадим текстовым редактором файл с текстом: Сессия 2017 года, заменим на Сессия 2018 года. #include "stdafx.h" #include "fstream" #include "iostream" //#include "istream" #include { char ch; fstream ff( "A.txt" ); if (!ff) { cout<< "No open" ; system( "pause" ); return 1; } //пропустить слово сессия ff.get(ch); while ( ch!= ' ' ) { cout< //заменить 2017 на 2018 ff.put( '2' );ff.put( '0' );ff.put( '1' );ff.put( '8' ) ; //запись в буфер if (!ff.good()) { cout<< "ERROR input" < ); return 1; } //вытолкнуть из буфера в файл ff.flush(); //Прочтать остальные смволы файла,должно выть year ff.get(ch); while (!ff.eof()) { cout< { cout<< "ERROR output" < ); return 2; } return 0; } 14.9.2 Организация прямого доступа к записям двоичного файла Двоичный файл с записями фиксированной длины можно рассматривать как массив. Для таких файлов реализован аппарат прямого доступа к элементам, подобно индексу в массивах. С такими двоичными файлами связано понятие указателя. При выполнении операции ввода или вывода указатель перемещается вперед. Указатель ввода и вывода. При чтении или записи одной записи указатель увеличивается на размер одной записи. Используя функции произвольного доступа istream &seekg(offset, origin) ; ostream &seekp(offset, origin) можно смещаться по файлу на определенное количество записей, от позиции в файле: от начала файла, от текущей позиции, от конца файла. offset – количество байтов на которое надо сместиться от позиции origin, вперед или назад по записям файла. origin – позиция, от которой начинается смещение, определяется значениями: ios::beg – от начала файла ios::cur – от текущей позиции ios::end – от конца файла Функция |