Как уже упоминалось, ввод-вывод по умолчанию является буферизованным (см. рис. 14.1). Для выходных потоков это фактически означает, что поток направляет символы буферу, а реальный вывод осуществляет уже буфер (см. п. 27.5 в [1]). Входной поток получает символы от буфера, а реальный ввод с устройства осуществляет буфер. Отменить буферизацию можно, установив флаг uni tbuf.
Если в библиотеке <cstdio> буфер представляет собой просто область памяти и функции ввода-вывода работают с этой памятью, то в объектно-ориентированной библиотеке буферы — это полноценные объекты. Конкретный тип буфера зависит от вида потока, но базовым типом для любых буферов является тип streambuf (см. п. п. 27.5.2 в [1]). Это обеспечивает единый для любых типов потоков интерфейс с буферами. С объектом типа streambuf можно обращаться непосредственно, используя многочисленные предоставляемые методы, например читать и записывать символы. Однако знать детали интерфейса класса streambuf необходимо только разработчикам систем ввода-вывода.
Каждый объект-поток содержит указатель на некоторый объект-буфер. Один из важнейших методов потока — метод rdbuf () (см. п. п. 27.4.4.2 в [1]), который возвращает этот указатель. С помощью данного метода можно записать функцию копирования (см. листинг 14.4) в одну строку (листинг 14.24).
Листинг 14.24. Копирование потоков
void filecopy(ifstream &in, ofstream &out) { out << in.rdbuf(); }
Мы просто выводим целиком весь буфер одного потока в другой. Таким же способом мы можем вывести текстовый файл в стандартный поток cout, например:
istream f("с:/textfiles/number.txt"); cout << f.rdbuf();
В классах basici stream и basicostream есть конструкторы, принимающие в качестве аргумента указатель на буфер. Это позволяет объявить несколько разных потоков, связанных с одним буфером. Например, мы можем объявить и настроить отдельный поток для вывода в cout целых в шестнадцатеричной форме:
ostream hout(cout.rdbuf());
hout.setf(ios::hex, ios::basefield);
hout.setf(ios:.showbase);
Пример:
hout << "hout=" « 77 « ' ';
cout << ncout=" << 77; hout << endl;
Эти операторы выведут на экран следующее: hout=0x4d cout=77
С помощью того же метода rdbuf () выполняется и перенаправление потоков, например:
ofstream f1le("c:/textfiles/cout.txt");
streambuf *b = cout.rdbuf();
cout.rdbuf(file.rdbuf());
cout << "привет от русской строки!" << endl;
cout.rdbuf(b);
cout << "привет от русской строки!,r << endl;
Найти http://ritualtrans.ru/ вы можете тут.
В этом фрагменте объявляется поток file, связанный с текстовым файлом. Затем сохраняется указатель на буфер стандартного потока. Непосредственно перенаправление стандартного потока в файл выполняется в третьей строке. После этого вывод в cout направляется в файл. Затем мы восстанавливаем буфер стандартного потока, и следующий оператор демонстрирует вывод уже на экран.
Примечательно, что открыв файл cout.txt в Блокноте, мы обнаружим, что текстовая константа записана на кириллице без всякой перекодировки! |