Работа с потоками
Шаблон класса if stream позволяет работать с файловыми потоками и производить ввод объектов произвольного типа. Удобно вводить объекты прямо в контейнер. Специальный итератор (istream_iterator) помогает в этом случае воспользоваться алгоритмами (например, сору). При достижении конца потока (end of stream) итератор принимает специальное значение, которое служит барьером выхода за пределы потока (past-the-end iterator).
В примере, приведенном ниже, используется еще один тип итератора (back_insert_iterator). Он является адаптером, позволяющим вставлять элементы в конец последовательности. Если использовать прямой inserter, то при чтении из файла последовательность будет реверсирована (перевернута). Позиционирование в потоке осуществляется с помощью метода seekg, техника использования которого также демонстрируется в примере:
void main () { //========== Вектор строк vector<string> v; v.push_back("Something in the way "); v.push_back("it works distracts me "); v.push_back("like no other matter"); pr(v,"Before writing to file"); //========== Запрашиваем имя файла cout << "\nEnter File Name: "; string fn, text; cin >> fn; //========== Приписываем расширение int pos = fn.rfind("."); if (pos > 0) fn.erase(pos); fn += ".txt"; //========== Создаем и открываем поток ofstream os(fn.c_str()); //========== Определяем входной и выходной потоки typedef istream_iterator<string, char, char_traits<char> > Strln; typedef ostream_iterator<string, char, char_traits<char> > StrOut; //========== Копируем контейнер в выходной поток copy (v.begin(), v.end(), StrOut(os,"\n")); os.close(); //========== Открываем файл для чтения if stream is(fn.c_str()); //========= Пропуск 17 символов is.seekg(17); is >> text; cout << "\n\nStream Positioning:\n\n" << "17 bytes:\t\t" << text << endl; //========== Устанавливаем в начало потока is.seekg(0, ios_base::beg); is >> text; cout << "0 bytes:\t\t" << text << endl; //========== Сдвигаем на 8 символов от конца is.seekg(-8, ios_base::end); is >> text; cout << "-8 bytes from end:\t" << text << "\n\n"; //========== Устанавливаем в начало потока is.seekg(0, ios_base::beg); v.clear (); //========== Копируем в контейнер copy(Strln(is),Strln(),back_inserter(v)); pr(v,"After reading from file"); cout<<"\n\n"; }
Программа производит следующий выход:
Before writing to file # Sequence: 1. Something in the way 2 .it works distracts me 3 .like no other matter Enter File Name: test Stream Positioning: 17 bytes: way 0 bytes: Something -8 bytes from end: matter After reading from file # Sequence: 1. Something 2 .in 3 .the 4 .way 5 .it 6 .works 7 .distracts 8 .me 9 .like 10 .no 11 .other 12 .matter