I am writing a code where I have to print the same data on the console and to a file. Is there a way to populate a common output stream object and then display it on console using cout and export it to a file, using fstream and iostream libraries?
Is there a way to create a common output stream object to print on the console and to a file in c++?
Asked
Active
Viewed 563 times
5
-
3Use a [`boost::iostreams::tee_device`](http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/functions/tee.html). – David G Nov 30 '14 at 18:25
-
I would recommend you do this in the calling environment. – Lightness Races in Orbit Nov 30 '14 at 18:51
1 Answers
6
Sure. You'd just create a suitable stream buffer which probably stores to other stream buffers it writes to internally. Using this stream buffer you'd then create an std::ostream
you are writing to.
For example, here is a simple implementation of this approach:
#include <streambuf>
#include <ostream>
class teebuf
: public std::streambuf
{
std::streambuf* sb1_;
std::streambuf* sb2_;
int overflow(int c) {
typedef std::streambuf::traits_type traits;
bool rc(true);
if (!traits::eq_int_type(traits::eof(), c)) {
traits::eq_int_type(this->sb1_->sputc(c), traits::eof())
&& (rc = false);
traits::eq_int_type(this->sb2_->sputc(c), traits::eof())
&& (rc = false);
}
return rc? traits::not_eof(c): traits::eof();
}
int sync() {
bool rc(false);
this->sb1_->pubsync() != -1 || (rc = false);
this->sb2_->pubsync() != -1 || (rc = false);
return rc? -1: 0;
}
public:
teebuf(std::streambuf* sb1, std::streambuf* sb2)
: sb1_(sb1), sb2_(sb2) {
}
};
class oteestream
: private virtual teebuf
, public std::ostream {
public:
oteestream(std::ostream& out1, std::ostream& out2)
: teebuf(out1.rdbuf(), out2.rdbuf())
, std::ostream(this) {
this->init(this);
}
};
#include <fstream>
#include <iostream>
int main()
{
std::ofstream fout("tee.txt");
oteestream tee(fout, std::cout);
tee << "hello, world!\n";
}

Dietmar Kühl
- 150,225
- 13
- 225
- 380
-
1A custom stream-buffer might be overkill here though. Saving to a `stringstream` and outputting that twice might be good enough. Anyway, good one. (BTW: You had that code lying around?) – Deduplicator Nov 30 '14 at 18:24
-
1@Deduplicator: yes, there is a solution which is a PITA to use and a proper solution which is nice to use. Wrapping the stream buffer into a `std::ostream` make the tee stream buffer quite nice to use. ... and, yes, I had this code lying around: I'm not typing _that_ fast :-) – Dietmar Kühl Nov 30 '14 at 18:31