What I want to do
redirect stdout and stderr to one or more files from inside c++
Why I need it
I am using an external, pr
For C++ iostreams, you can use the non-const overload of rdbuf
to set std::cout
to a std::filebuf
. (This is best done by
means of an RAII class, since you have to restore it before
leaving main.) For C FILE*
, you can use freopen
, but
I don't think you'll be able to restore it.
FWIW: both of these solutions use only standard C++ or C, so should be portable.
I was inspired by @POW and @James Kanze 's answers and put together a little RAII class for redirecting std::cout
to a file. It is intended to demonstrate the principle.
Code:
#include <iostream>
#include <fstream>
#include <string>
// RAII for redirection
class Redirect {
public:
explicit Redirect(const std::string& filenm):
_coutbuf{ std::cout.rdbuf() }, // save original rdbuf
_outf{ filenm }
{
// replace cout's rdbuf with the file's rdbuf
std::cout.rdbuf(_outf.rdbuf());
}
~Redirect() {
// restore cout's rdbuf to the original
std::cout << std::flush;
_outf.close(); ///< not really necessary
std::cout.rdbuf(_coutbuf);
}
private:
std::streambuf* _coutbuf;
std::ofstream _outf;
};
// == MAIN ==
int main(int argc, char* argv[]) {
std::cout << "This message is printed to the screen" << std::endl;
{
// scope for the redirection
Redirect redirect{ "output.txt" };
std::cout << "This message goes to the file" << std::endl;
}
std::cout << "Printing to the screen again" << std::endl;
}
Output:
This message is printed to the screen
Printing to the screen again
Contents of the file "output.txt"
:
This message goes to the file
well i u'd better use freopen()
Usage Syntax:
freopen("RedToFile","r",stdout);
or
freopen("/dev/null","a",stdout);
the same goes for "stderr"
Are you looking for something like this :-
int main()
{
// Save original std::cin, std::cout
std::streambuf *coutbuf = std::cout.rdbuf();
std::streambuf *cinbuf = std::cin.rdbuf();
std::ofstream out("outfile.txt");
std::ifstream in("infile.txt");
//Read from infile.txt using std::cin
std::cin.rdbuf(in.rdbuf());
//Write to outfile.txt through std::cout
std::cout.rdbuf(out.rdbuf());
std::string test;
std::cin >> test; //from infile.txt
std::cout << test << " "; //to outfile.txt
//Restore back.
std::cin.rdbuf(cinbuf);
std::cout.rdbuf(coutbuf);
}
From my earlier answer
In addition to afr0ck answer of freopen() I want to say that while using freopen()
we should be careful. Once a stream like stdout
or stdin
is reopened with assigning the new destination(here the 'output.txt' file) always it remains for a program unless it has been explicitly change.
freopen("output.txt", "a", stdout);
Here the standard output stream stdout
is reopened and assigned with the 'output.txt' file. After that whenever we use printf()
or any other stdout
stream like - putchar()
then every output will goes to the 'output.txt'. To get back the default behavior (that is printing the output in console/terminal) of printf()
or putchar()
we can use the following line of code -
freopen("/dev/tty", "w", stdout);
freopen("CON", "w", stdout);
See the code example below -
#include <stdio.h>
int main() {
printf("No#1. This line goes to terminal/console\n");
freopen("output.txt", "a", stdout);
printf("No#2. This line goes to the \"output.txt\" file\n");
printf("No#3. This line aslo goes to the \"output.txt\" file\n");
freopen("/dev/tty", "w", stdout); /*for gcc, diffrent linux distro eg. - ubuntu*/
//freopen("CON", "w", stdout); /*Mingw C++; Windows*/
printf("No#4. This line again goes to terminal/console\n");
}
This code generate a 'output.txt' file in your current directory and the No#2 and No#3 will be printed in the 'output.txt' file.
Thanks
If you want to be able to reuse it, don't close stdoutfd
in restore_stdout
.