Redirect stdout / stderr to a file under unix C ++ - again

What i want to do

redirect stdout and stderr to one or more files from inside C ++

Why do I need it

I use an external, precompiled third-party library that produces an ridiculous amount of output that I would like to redirect to the log file to keep the console clean.

Terms

Compatibility is not a problem, the code will only work on Unix systems. Redirection should affect not only C ++ style printing (std :: cout <"hello world" <std :: endl), but also c style printing (printf ("hello world \ n")).

What have i tried so far

I looked through stackoverflow for noon, reading several answers to people having similar problems. Using these answers, I was able to compile the following code snippet:


#include <stdio.h> #include <iostream> #include <fcntl.h> #include "unistd.h" const int stdoutfd(dup(fileno(stdout))); int redirect_stdout(const char* fname){ fflush(stdout); int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); dup2(newstdout, fileno(stdout)); close(newstdout); } int restore_stdout(){ fflush(stdout); dup2(stdoutfd, fileno(stdout)); close(stdoutfd); return stdoutfd; } int main(){ redirect_stdout("/dev/null"); std::cout << "invisible 1" << std::endl; restore_stdout(); std::cout << "visible 1" << std::endl; redirect_stdout("/dev/null"); std::cout << "invisible 2" << std::endl; restore_stdout(); std::cout << "visible 2" << std::endl; return 0; } 

What I expect to see:

 visible 1 visible 2 

What I really see

 visible 1 

That is, when using this mechanism for the first time, it works, but if it is used again, recovery of the output will not work. Can someone tell me what I need to change for the mechanism to work infinitely often?

+6
source share
5 answers

If you want to use it again, do not close stdoutfd in restore_stdout .

+4
source

You are 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 previous answer

+1
source

Well, it is better to use freopen ()

Usage Syntax:

 freopen("RedToFile","r",stdout); or freopen("/dev/null","a",stdout); 

same for "stderr"

+1
source

For C ++ iostreams, you can use the non-constant rdbuf overload to set std::cout to a std::filebuf . (This is best done with RAII class tools, since you have to restore it to leaving the main one.) For C FILE* you can use freopen , but I donโ€™t think you can restore it.

FWIW: both of these solutions use only standard C ++ or C, so they should be portable.

0
source

In addition to afr0ck, the answer is freopen () I want to say that when using freopen() we have to be careful. When a stream, like stdout or stdin , opens again with a new destination (here 'output.txt' ), it always remains for the program, unless it has clearly changed.

 freopen("output.txt", "a", stdout); 

Here, the standard output stream stdout reopened and assigned by the file 'output.txt' . After that, whenever we use printf() or any other stdout stream, such as putchar() , each output will go to 'output.txt' . To return the default behavior (i.e. print the output in the console / terminal) printf() or putchar() , we can use the following line of code -

  • for gcc, a Linux distribution, for example ubuntu, freopen("/dev/tty", "w", stdout);
  • for Mingw C / C ++, windows - 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 generates the file 'output.txt' in your current directory, and No # 2 and No # 3 will be printed in the 'output.txt' file.

thanks

0
source

Source: https://habr.com/ru/post/951148/


All Articles