C++:重定向STDOUT

Cha*_*arx 48 c++

在我的应用程序中,我想将通常转到stdout流的输出重定向到我定义的函数.我读到你可以将stdio重定向到一个文件,为什么不用一个函数呢?

例如:

void MyHandler( const char* data );

//<<Magical redirection code>>

printf( "test" );
std::cout << "test" << std::endl;

//MyHandler should have been called with "test" twice, at this point
Run Code Online (Sandbox Code Playgroud)
  • 我怎样才能实现这种/类似的行为?

zpa*_*ack 42

@Konrad Rudolph是对的,你可以轻松完成这项工作,至少对于cout/cerr/clog来说.您甚至不需要自己的streambuf实现,只需使用ostringstream即可.

// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );

// This goes to the string stream.
cout << "Hello, World!" << endl;

// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );

// Will output our Hello World! from above.
cout << strCout.str();
Run Code Online (Sandbox Code Playgroud)

同样的事情适用于cerr和clog,但根据我的经验,一般不适用于stdout/stderr,因此printf不会输出.cout转到stdout,但重定向cout不会重定向所有stdout.至少,那是我的经历.

如果数据量预计很小,则freopen/setbuf工作正常.我最终做了更好的dup/dup2重定向到管道.

更新:我写了一篇博文,展示了我最终使用的dup2方法,你可以在这里阅读.它是为OS X编写的,但可能适用于其他Unix版本.我非常怀疑它在Windows中是否可行.Cocoa版同样在这里.

  • 有用,但不适用于这个问题.要求重定向stdout. (6认同)

Kon*_*lph 9

所有其他答案都是错误的.您可以这样做,并且您不需要求助于freopen任何其他C或非标准功能.

相反,您需要创建自己的std::streambuf实现,即您自己的流缓冲区.

完成后,您可以cout通过切换缓冲区来重定向流:

your_stream_buffer new_buffer;
streambuf* old_buffer = cout.rdbuf(&new_buffer);

cout << "Hello"; // This will be redirected to `new_buffer`.

// Restore original buffer:
cout.rdbuf(old_buffer);
Run Code Online (Sandbox Code Playgroud)

由于我自己从未这样做过,所以我无法准确地告诉你实现的效果如何streambuf.我的建议是查看文档并执行一个虚拟实现,为所有已实现的函数打印诊断.这应该有助于弄清楚班级的运作方式.

或者,查看一下您所选择的C++参考书来描述streambuf该类.

  • 不,特别要求重定向stdout的解决方案(即使您认为通常不需要).给出的示例是重定向cout和重定向printf输出.您的解决方案不适用于printf(或其他stdout输出源).我提到这个因为我还需要重定向stdout,谷歌指出我这个问题,并且2个最高投票的答案没有达到要求或我(以及其他任何人发现这个问题而不是"重定向cout")需要.为什么不自己发布"重定向cout"问题,并回答它?这是一个很好的解决方案. (5认同)
  • @ user664303 [X/Y问题](http://meta.stackexchange.com/q/66377/1968).OP希望将对std :: cout`的调用重定向到其处理程序.我的代码确实如此.它不会重定向底层操作系统,流,true,但这通常*不是必需的,而且更难实现,而不是以独立于平台的方式. (2认同)

ste*_*fan 5

答案:是的,可以通过复制。正如您所说,freopen 只会重新打开文件的标准输出。

查看如何在内存中缓冲 stdout 并从专用线程写入它


小智 5

可以通过取消引用其指针来禁用stdin/stdout:

FILE fp_old = *stdout;  // preserve the original stdout
*stdout = *fopen("/dev/null","w");  // redirect stdout to null
HObject m_ObjPOS = NewLibraryObject(); // call some library which prints unwanted stdout
*stdout=fp_old;  // restore stdout
Run Code Online (Sandbox Code Playgroud)


Foo*_*Bah -1

您可以使用 sprintf 写入字符数组,然后读取值:

char buf[1024];
sprintf(buf, "test");
MyHandler(buf);
Run Code Online (Sandbox Code Playgroud)

还有 snprintf 和其他一些取决于平台

  • 我认为OP想保留所有的“printf”调用,而只是重定向它们。 (3认同)