如何组合输出流,以便输出同时到达多个位置?
我想将两个(或更多)流合成为一个。我的目标是任何定向到 cout
、cerr
和 clog
的输出也与原始流一起输出到文件中。 (例如,当事情记录到控制台时。关闭后,我仍然希望能够返回并查看输出。)
我正在考虑做这样的事情:
class stream_compose : public streambuf, private boost::noncopyable
{
public:
// take two streams, save them in stream_holder,
// this set their buffers to `this`.
stream_compose;
// implement the streambuf interface, routing to both
// ...
private:
// saves the streambuf of an ios class,
// upon destruction restores it, provides
// accessor to saved stream
class stream_holder;
stream_holder mStreamA;
stream_holder mStreamB;
};
这看起来很简单。然后 main 中的调用将类似于:
// anything that goes to cout goes to both cout and the file
stream_compose coutToFile(std::cout, theFile);
// and so on
我还查看了 boost::iostreams,但没有看到任何相关内容。
还有其他更好/更简单的方法来实现这一点吗?
I'd like to compose two (or more) streams into one. My goal is that any output directed to cout
, cerr
, and clog
also be outputted into a file, along with the original stream. (For when things are logged to the console, for example. After closing, I'd like to still be able to go back and view the output.)
I was thinking of doing something like this:
class stream_compose : public streambuf, private boost::noncopyable
{
public:
// take two streams, save them in stream_holder,
// this set their buffers to `this`.
stream_compose;
// implement the streambuf interface, routing to both
// ...
private:
// saves the streambuf of an ios class,
// upon destruction restores it, provides
// accessor to saved stream
class stream_holder;
stream_holder mStreamA;
stream_holder mStreamB;
};
Which seems straight-forward enough. The call in main then would be something like:
// anything that goes to cout goes to both cout and the file
stream_compose coutToFile(std::cout, theFile);
// and so on
I also looked at boost::iostreams
, but didn't see anything related.
Are there any other better/simpler ways to accomplish this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您想纯粹在 stdlib 内完成此操作,那么您确实拥有正确的设计。
一件事:不要在每个输出上使用每个流缓冲区,而是将其实现为使用与给定的流缓冲区之一相同的放置区域,并在溢出和同步时复制到其他流缓冲区。这将最大限度地减少虚拟调用,这是 Streambuf 工作的目标之一。
或者,如果您只想处理 stdout & stderr(这是常见的),通过标准 Unix
tee
程序(或您平台上的等效程序)运行您的程序,可以在调用程序时自己执行此操作,也可以在程序中通过分叉、设置适当地向上流,等等。编辑:你让我思考,我应该知道如何做到这一点。这是我的第一个 近似值。 (当这个中断时,你可以保留这两部分。)
现在,这个测试还远未完成,但它似乎有效:
将其与文件放在一起:
You do have the right design—if you want to do this purely within the stdlib.
One thing: instead of teeing to each streambuf on every output, implement it to use the same put area as one of the streambufs it's given, and copy to the others on overflow and sync. This will minimize virtual calls, which is one of the goals of how streambufs work.
Alternatively, and if you want to only handle stdout & stderr (which is common), run your program through the standard Unix
tee
program (or the equivalent on your platform), either by doing it yourself when invoking the program, or within the program by forking, setting up the streams as appropriate, etc.Edit: You got me thinking, and I should know how to get this right. Here's my first approximation. (When this breaks, you get to keep both pieces.)
Now, this test is far from complete, but it seems to work:
Put it together with a file:
您提到在 Boost.IOStreams 中没有找到任何内容。您是否考虑过 tee_device?
You mention having not found anything in Boost.IOStreams. Did you consider tee_device?
我会编写一个自定义流缓冲区,它仅将数据转发到所有链接流的缓冲区。
I would write a custom stream buffer that just forwards data to the buffers of all your linked streams.