Файловые потоки ввода-вывода.


Тема 5: Файловые потоки ввода-вывода.
5.1. Использование потоков ввода-вывода.
С помощью перегрузки операторов ввода и вывода можно заставить компилятор распознавать в операторах ввода-вы-вода один или несколько необходимых классов. Рассмотрим как создаются потоковые классы.
5.1.1. Перегрузка операторов вывода в поток

Обычно потоки вывода поддерживают только стандартные типы данных. С помощью перегрузки оператора вывода в поток << можно заставить выражения выводить объекты собст-венных классов.

// Программа 1

#include <iostream.h>
class TPoint {
private:
int x,y;
public:
TPoint() { x = y = 0;}
TPoint(int xx, int yy) { x = xx; y = yy; }
void PutX(int xx) { x = xx; }
void PutY(int yy) { y = yy; }
int GetX(void) { return x; }
int GetY(void) { return y; }
friend ostream& operator<< (ostream& os, TPoint &p);
};
void main()
{
TPoint p;
cout << p << endl;
p.PutX(100);
p.PutY(200);
cout << p << endl;
}
ostream& operator<< (ostream& os, TPoint &p)
{
os << » x== » << p.x << «, y == » << p.y ;
return os;
}
Поток вывода перегружен в виде дружественной функции. Так как функция возвращает ссылку на osteram то можно выво-дить несколько объектов в одном операторе вывода в поток.
cout << p1 << p2 << p3 << p4;

5.1.2. Перегрузка операторов ввода из потока

С помощью перегрузки оператора ввода из потока >> мож-но читать объекты класса.
friend istream& operator>> (istream& is, TPoint &p);
cin >> p;
cout << endl << «You entered: » << p;
}
istream& operator>> (istream& is, TPoint &p)
{
is >> p.x >> p.y ;
return is;
}

5.2. Файловые потоки.

Файловые потоки представляют объектно-ориентированный
способ чтения и записи информации в дисковые файлы. Библио-тека файловых потоков разработана для работы только с тек-стовыми файлами. Однако можно применить ее и для чтения и записи двоичных значений, текстов, структур или любых дру-гих объектов.
Класс файловых потоков подключается заголовочными фай-лами fstream.h и iostream.h. Нужно учесть несколько моментов при использовании файловых потоков.
— все классы файловых потоков, за исключением filebuf, — производные от класса ios. Благодаря своей наследственности они могут использовать функции-члены, манипуляторы, флажки состояния и другие методы обработки потоков из файла iostream.h.
— для чтения данных из файлов используйте класс ifstream, производный от класса istream.
— для выходных файлов используйте класс ofstream, произ-водный от класса ostream.
— для чтения и записи в один файл используйте класс fstream.
— класс filebuf предоставляет буферизованный сервис ввода-вывода для этих классов.

5.2.1. Потоки текстовых файлов.

Использование потоков текстовых файлов состоит из трех основных моментов:
— создание текстового файла;
— запись в текстовые файлы;
— чтение из текстовых файлов.
Чтобы создать новый текстовый файл, определите объект класса ofstream и передайте конструктору класса два аргу-мента: имя файла и значение режима открытия:
ofstream ofs(«Newfile.txt», ios::out);
Если файл уже существует, то это приведет к перезаписыванию этого файла. Аргумент ios::out определяет режим доступа к файлу. Это константы перечислимого типа open_mode. Можно задать сразу несколько опций путем бъединения констант в выражениях логической операции ИЛИ. Константы open_mode:
app — операция записи добавляет новую информацию в конец файла;
ate — при открытии разыскивает конец файла;
binary — открывает файл в двоичном формате;
in — открывает файл для чтения;
nocreate — если файл не существует, то новый не открывает-ся;
noreplace -если файл уже существует, то не перезаписывает-ся;
out — открывает файл для записи.
После создания или перезаписи всегда проверяйте, что объект готов к использованию
ofstream ofs(«Newfile.txt», ios::out);
if (!ofs) { /вызывается функция operator!
cerr << «Error: unable to write to Newfile.txt » << endl;
exit(1);
}
Файловые потоки являются объектно-ориентированны-ми.Чтобы открыть файл, достаточно создать объект входного файлового потока, а затем использовать потоковые операторы для чтения из файла. Чтобы записать или создать файл, постройте объект выходного файлового потока и используйте потоковые операторы для записи в файл. Когда объект файло-вого потока выходит за пределы области определения или удаляется, файл автоматически закрывается.
Существует четыре важных метода, которые важно освоить:
— Посимвольное чтение текста.
— Посимвольная запись текста.
— Построчное чтение из текста.
— Построчная запись текста.

а) Посимвольное чтение из текста.

// Программа 2

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc <= 1 ) {
cerr << «Error: filename missing» << endl;
exit(1);
}
ifstream ifs(argv[1], ios::in);
if (!ifs) {
cerr << «Error: unable to open » << argv[1] << endl;
exit(2);
}
char c;
long nc = 0, nl = 0;
while (ifs.get(c)) {
if( c == ‘\n’)
nl++; //считает количество строк
else
nc++; //количество символов
cout.put(c);
}
cout << endl << endl << «Total characters : » << nc;
cout << endl << «Number of lines : » << nl;
return 0;
}

б) Посимвольная запись текста.

// Программа 3

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc <= 1 ) {
cerr << «Error: filename missing» << endl;
exit(1);
}
ifstream ifs(argv[1], ios::in); //проверка существования такого файла
if (ifs) { //вызывается перегруженная функция operator void *
cerr << «Error: » << argv[1] << «already exists» << endl;
cerr << «Specify a different filename » << endl;
exit(2);
}
ofstream ofs(argv[1], ios::out); //создание выходного потока
if (!ofs) {
cerr << «Error: unable to write to » << argv[1] << endl;
exit(3);
}
ofs << «1: a string\n»;
ofs.put(‘2’);
ofs.put(‘:’);
ofs.put(‘ ‘);
ofs.put(‘C’).put(‘a’).put(‘r’).put(‘s’);
ofs << endl;
return 0;
}

в) Построчное чтение текста.

// Программа 4

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#include <string.h>
#define BUFLEN 128
int main(int argc, char *argv[])
{
if ( argc <= 1 ) {
cerr << «Error: filename missing» << endl;
exit(1);
}
ifstream ifs(argv[1], ios::in);
if (!ifs) {
cerr << «Error: unable to open » << argv[1] << endl;
exit(2);
}
char buffer[BUFLEN];
long nc = 0, nl = 0;
while (!ifs.eof()) {
ifs.getline(buffer, sizeof(buffer),’\n’);
if( !(ifs.eof() && strlen(buffer) ==0)) {
nc+= strlen(buffer);
nl++;
cout << buffer << endl;
}
}
cout << endl << endl << «Total characters : » << nc;
cout << endl << «Number of lines : » << nl;
return 0;
}

г) Построчная запись текста.

// Программа 5

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#include <string.h>
#define STR «2: Another literal string»
int main(int argc, char *argv[])
{
if ( argc <= 1 ) {
cerr << «Error: filename missing» << endl;
exit(1);
}
ifstream ifs(argv[1], ios::in);
if (ifs) {
cerr << «Error: » << argv[1] << «already exists» << endl;
cerr << «Specify a different filename » << endl;
exit(2);
}
ofstream ofs(argv[1], ios::out);
if (!ofs) {
cerr << «Error: unable to write to » << argv[1] << endl;
exit(3);
}
ofs << «1: A literal string» << endl;
ofs.write(STR, strlen(STR));
ofs << endl;
char *c = » String addressed by pointer»;
ofs << «3: » << c << endl;
return 0;
}

Для перемещения указателя внутри файла служат функции seekp() и seekg(), которые позволяют переходить на произ-вольную позицию в файле. Для файла, открытого для чтения, используется функция seekg(), для файла, открытого для записи – seekp().
Например для перехода на начало или конец файла:
input_file.seekg(0,ios::beg);
output_file.seekp(0,ios::end);
на произвольную позицию:
input_file.seekg(20,ios::beg); //от начала
input_file.seekp(-10,ios::end); //от конца
input_file.seekpg(50,ios::cur); //от текущей позиции

Загрузка...