Redirect Both Cout and Stdout to a String in C++ for Unit Testing

Redirect both cout and stdout to a string in C++ for Unit Testing

std::stringstream may be what you're looking for.

UPDATE
Alright, this is a bit of hack, but maybe you could do this to grab the printf output:

char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout);
setbuf(stdout, huge_string_buffer);

Note you should use "/dev/null" for linux instead of "NUL". That will rapidly start to fill up huge_string_buffer. If you want to be able to continue redirecting output after the buffer is full you'll have to call fflush(), otherwise it will throw an error. See std::setbuf for more info.

redirect stdout/stderr to a string

Yes, you can redirect it to an std::stringstream:

std::stringstream buffer;
std::streambuf * old = std::cout.rdbuf(buffer.rdbuf());

std::cout << "Bla" << std::endl;

std::string text = buffer.str(); // text will now contain "Bla\n"

You can use a simple guard class to make sure the buffer is always reset:

struct cout_redirect {
cout_redirect( std::streambuf * new_buffer )
: old( std::cout.rdbuf( new_buffer ) )
{ }

~cout_redirect( ) {
std::cout.rdbuf( old );
}

private:
std::streambuf * old;
};

redirect output of an function printing to console to string

Yes. That can be done. Here is a little demo:

#include <sstream>
#include <iostream>

void print_to_console() {
std::cout << "Hello from print_to_console()" << std::endl;
}

void foo(){
std::cout<<"hello world"<<std::endl;
print_to_console(); // this could be printed from anything
}
int main()
{
std::stringstream ss;

//change the underlying buffer and save the old buffer
auto old_buf = std::cout.rdbuf(ss.rdbuf());

foo(); //all the std::cout goes to ss

std::cout.rdbuf(old_buf); //reset

std::cout << "<redirected-output>\n"
<< ss.str()
<< "</redirected-output>" << std::endl;
}

Output:

<redirected-output>
hello world
Hello from print_to_console()
</redirected-output>

See Online Demo.

How to get output sent to stdout onto a string

Use rdbuf.

std::stringstream stream;
auto * old = std::cout.rdbuf(stream.rdbuf());
CallFunction();
std::cout.rdbuf(old);
std::string value = stream.str();

How to capture stdout/stderr with googletest?

I have used this snippet before to redirect cout calls to a stringstream when testing output. Hopefully it might spark some ideas. I've never used googletest before.

// This can be an ofstream as well or any other ostream
std::stringstream buffer;

// Save cout's buffer here
std::streambuf *sbuf = std::cout.rdbuf();

// Redirect cout to our stringstream buffer or any other ostream
std::cout.rdbuf(buffer.rdbuf());

// Use cout as usual
std::cout << "Hello World";

// When done redirect cout to its old self
std::cout.rdbuf(sbuf);

Before redirecting back to the original output use your google test to check the output in buffer.

How to redirect cin and cout to files?

Here is an working example of what you want to do. Read the comments to know what each line in the code does. I've tested it on my pc with gcc 4.6.1; it works fine.

#include <iostream>
#include <fstream>
#include <string>

void f()
{
std::string line;
while(std::getline(std::cin, line)) //input from the file in.txt
{
std::cout << line << "\n"; //output to the file out.txt
}
}
int main()
{
std::ifstream in("in.txt");
std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!

std::ofstream out("out.txt");
std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!

std::string word;
std::cin >> word; //input from the file in.txt
std::cout << word << " "; //output to the file out.txt

f(); //call function

std::cin.rdbuf(cinbuf); //reset to standard input again
std::cout.rdbuf(coutbuf); //reset to standard output again

std::cin >> word; //input from the standard input
std::cout << word; //output to the standard input
}

You could save and redirect in just one line as:

auto cinbuf = std::cin.rdbuf(in.rdbuf()); //save and redirect

Here std::cin.rdbuf(in.rdbuf()) sets std::cin's buffer to in.rdbuf() and then returns the old buffer associated with std::cin. The very same can be done with std::cout — or any stream for that matter.

Redirect FILE * stdout to string in c++

In linux, your best bet is anonymous pipe.

First, create a pipe:

int redirectPipe[2];
pipe(redirectPipe)

Then, open the file descriptor returned to us via pipe(2) using fdopen:

FILE* inHandle = fdopen(redirectPipe[0], "w");
FILE* outHandle = fdopen(redirectPipe[1], "r");

Call the function:

getInfo(inHandle, someValue);

Then, read using outHandle as if it's a regular file.

One thing to be careful: Pipes have fixed buffer size and if there is a possibility for getInfo function to fill the buffer, you'll have a deadlock.

To prevent the deadlock, you can either call getInfo from another thread, or increase pipe buffer size using fcntl and F_SETPIPE_SZ. Or better, as Ben Voigt mentioned in the comments, create a temp file.

Note: I was specific to *nix since OP mentioned he/she wanted the "best one in linux"

Redirecting stdout from another program in C++

You could create a filebuf then replace cout's streambuf with it:

{
std::filebuf f;
f.open("output.txt", std::ios::out);
std::streambuf* o = std::cout.rdbuf(&f);
std::cout << "hello" << std::endl; // endl will flush the stream
std::cout.rdbuf(o);
}

You need to restore cout's original streambuf again (or set it to a null pointer) or it will probably crash when the global streams are flushed and destroyed, because the filebuf will already have gone out of scope.



Related Topics



Leave a reply



Submit