Связывание потоков ввода-вывода. Перенаправление стандартных потоков данных

   
На этом шаге мы рассмотрим особенности перенаправления стандартных потоков ввода-вывода.

   
В старых реализациях библиотеки IOStream глобальные потоки данных cin, cout, cerr и clog были объектами классов
istream_withassign и ostream_withassign. Это позволяло перенаправлять потоки данных, присваивая одни потоки другим. Этот
механизм был исключен из стандартной библиотеки C++. Тем не менее сама возможность перенаправления потоков данных была сохранена
и расширена так, что теперь она может применяться ко всем потокам данных. Перенаправление потока данных осуществляется назначением потокового буфера.

   
В механизме назначения потоковых буферов перенаправление потоков данных находится под управлением программы, операционная система здесь не
участвует. Например, в результате выполнения следующего фрагмента данные, отправленные в поток данных cout, будут передаваться не в
стандартный выходной канал, а в файл cout.txt:

std::ofstream file ("cout.txt"); 
std::cout.rdbuf (file.rdbuf());

   
Для передачи всей форматной информации между потоками данных можно воспользоваться функцией copyfmt():

std::ofstream file ("cout.txt"); 
file.copyfmt (std::cout); 
std::cout.rdbuf (file.rdbuf());

   Замечание.
Объект file является локальным и уничтожается в конце блока, что также приводит к уничтожению соответствующего потокового буфера.
В этом отношении файловые потоки данных отличаются от "обычных", поскольку они создают свои объекты потоковых буферов во время конструирования
и уничтожают их при уничтожении.

   
Учитывая это замечание, в приведенном примере дальнейшее использование объекта cout для записи невозможно. Более того, его даже нельзя
безопасно уничтожить при завершении программы. По этой причине прежний буфер следует всегда сохранять с последующим восстановлением!
В представленном ниже примере это делается в функции redirect():

//---------------------------------------------------------------------------

#include <vcl.h>
// Заголовочные файлы для файлового ввода-вывода
#include <fstream>
#include <iostream>

#include <conio.h>   //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;

std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

void redirect(ostream&);

int main (int argc, char* argv[])
{
  cout << ToRus("Первая строка") << endl;

  redirect(cout);

  cout << ToRus("Последняя строка") << endl;

  getch();
  return 0;
}

void redirect (ostream& strm)
{
  ofstream file("redirect.txt");
    
  // Сохранение выходного буфера потока
  streambuf* strm_buffer = strm.rdbuf();
  // Перенаправление вывода в файл
  strm.rdbuf (file.rdbuf());

  file << ToRus("Последняя строка в файле") << endl;
  strm << ToRus("Последняя строка в потоке") << endl;

  // Восстановление старого выходного буфера
  strm.rdbuf (strm_buffer);

}  // Автоматическое закрытие файла и буфера


//---------------------------------------------------------------------------

Текст этого примера можно взять здесь.

   
Результат выполнения программы выглядит так:


Рис.1. Результат работы приложения

   
Содержимое файла redirect.txt:

  Последняя строка в файле
  Последняя строка в потоке

   
Как видите, данные, записанные в поток данных cout внутри функции redirect(), были переданы в файл (по имени параметра strm),
а даииые, записанные в main() после выполнения redirect(), попали в восстановленный выходной канал.

   
На следующем шаге мы рассмотрим потоки чтения и записи.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий