Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

In C, we can use the function freopen() to redirect an existing FILE pointer to another stream. The prototype of freopen() is

FILE * freopen ( const char* File name,const char* Mode, FILE * stream);
Copy the code

For example, to redirect standard output to a text file, we could write

freopen ("text_file.txt"."w", stdout);
Copy the code

Although C++ still supports this approach, this article discusses another way to redirect I/O streams. C++ is an object-oriented programming language that allows us not only to define our own streams, but also to redirect standard streams. Thus, in C++, a stream is an object whose rows are defined by a class. Therefore, anything that behaves like a flow is also a flow. There are three main types of Streams objects in C++ :

  • Istream: This type of stream object can only perform input operations from a stream
  • Ostream: These objects can only be used for output operations.
  • Iostream: Can be used for input and output operations

All of these classes, as well as the file stream classes, derive from the following classes: ios and Streambuf. Thus, file streams and IO stream objects behave similarly. All stream objects also have an associated data member stream buffer class. Simply put, a Streambuf object is a buffer for a stream. When we read data from a stream, we don’t read it directly from the source, but from a buffer linked to the source. Again, the output operation is performed on the buffer first, and then the buffer is flushed (written to the physical device) as needed. C++ allows us to set the stream buffer for any stream. Thus, the task of redirecting a flow is simply to change the flow buffer associated with the flow. Therefore, to redirect stream A to stream B, we need to do the following: –

  1. Get A’s stream buffer and store it somewhere
  2. Set A’s stream buffer to B’s stream buffer
  3. If you need to reset A’s stream buffer to its previous stream buffer

We can use the function ios::rdbuf() to perform two operations.

1) stream_object.rdbuf() : Returns a pointer to the stream buffer of stream_object2) stream_object.rdbuf(streambuf * p) : Sets the stream buffer to the object pointed to by PCopy the code

Here is a sample program to show the steps

// The Cpp program that redirects cout to a file
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main(a)
{
	fstream file;
	file.open("cout.txt", ios::out);
	string line;

	// Cout backup stream buffer
	streambuf* stream_buffer_cout = cout.rdbuf(a); streambuf* stream_buffer_cin = cin.rdbuf(a);// Get the streamBuffer of the file
	streambuf* stream_buffer_file = file.rdbuf(a);// Redirect cout to a file
	cout.rdbuf(stream_buffer_file);

	cout << "This line written to file" << endl;

	// Redirect cout back to the screen
	cout.rdbuf(stream_buffer_cout);
	cout << "This line is written to screen" << endl;

	file.close(a);return 0;
}
Copy the code

Output:

This line is written to screen
Contents of file cout.txt:
This line written to file
Copy the code

Note: The above steps can be condensed into one step

auto cout_buf = cout.rdbuf(file.rdbuf())

// Set the couts stream buffer and return the old
streambuffer back to cout_buf
Copy the code