output to 2 streams

F

Fraser Ross

My program outputs to cout and I want it to output to a LOG file as well.
Is there a simple way to do that?

Fraser.
 
S

Sharad Kala

Fraser Ross said:
My program outputs to cout and I want it to output to a LOG file as well.
Is there a simple way to do that?

How about this simple way -
std::eek:fstream out1("xxx.log");
....
std::cout << "Something to log and print";
out1 << "Something to log and print";

You could also use Macro trick to get this done, something like -

#define PRINT(xxx) std::cout << "Something to log and print"; \
out1 << "Something to log and print";

int main()
{
//...
PRINT ("Something to print");

}

-Sharad
 
S

Sharad Kala

this done, something like -
#define PRINT(xxx) std::cout << "Something to log and print"; \
out1 << "Something to log and print";

Should be --

#define PRINT(xxx) std::cout << xxx; \
out1 << xxx;
 
F

Fraser Ross

Can a ostream_iterator or ostreambuf_iterator be constructed from a
ostringstream? E.g.:
std::eek:stringstream oStr;
std::eek:stream_iterator it(oStr);

basic_ostringstream inherits from basic_ostream. ostream_iterator has a
constructor taking a basic_ostream.

Fraser.
 
F

Fraser Ross

An explicit specialisation is required.


std::eek:stream_iterator<std::basic_ostringstream::char_type,
std::basic_ostringstream::char_type> it(oStr);

Fraser.
 
J

Jonathan Turkanis

Fraser Ross said:
My program outputs to cout and I want it to output to a LOG file as well.
Is there a simple way to do that?

I have submitted a library to boost, to be reviewed around the
beginning of September, which allows this to be done easily

struct splitter : boost::io::sink {
tee(std::eek:stream& first, std::eek:stream& second)
: first(first), second(second)
{ }
void write(const char* s, std::streamsize n)
{
first.write(s, n);
second.write(s, n);
}
std::eek:stream& first;
std::eek:stream& second;
};

int main()
{
std::eek:fstream log("log.txt");
boost::io::stream_facade<splitter> out;
out.open(splitter(log, std::cout));
out << "this goes to cout and to log\n";
}

The library is here: http://tinyurl.com/3m6ur

Jonathan
 
O

Old Wolf

Sharad Kala said:
You could also use Macro trick to get this done, something like -

#define PRINT(xxx) std::cout << "Something to log and print"; \
out1 << "Something to log and print";

This would be bad if xxx had side effects.. how about:

struct tee_stream
{
template<typename T>
tee_stream &operator<< (T const &t) {
std::cout << t;
other_stream << t;
return *this;
}
};
 
R

Rolf Magnus

Old said:
This would be bad if xxx had side effects.. how about:

struct tee_stream
{
template<typename T>
tee_stream &operator<< (T const &t) {
std::cout << t;
other_stream << t;
return *this;
}
};

Try:

tee_stream mystream;
mystream << std::endl;
 
M

Martin Sebor

Fraser Ross said:
My program outputs to cout and I want it to output to a LOG file as well.
Is there a simple way to do that?

Sure: program | tee LOG :)

Martin
 
S

Sharad Kala

Interesting, why doesn't this work exactly?

Because std::endl is a pointer to a function and is un-implemented for
tee_stream.
So a rough implementation to make it work with std::endl is to add this in
tee_stream class-
typedef ostream& (*manipT)(ostream&);
tee_stream & operator<< (manipT manip)
{
((*manip)(cout));
((*manip)(other_stream));
return *this;
}

-Sharad
 
F

Fraser Ross

I have made improvements to the igzstream and ogzstream classes available
from the link to "zlib C++ wrapper" at the zlib home page. They fix a bug
with gzstreambuf::close() as well as mainly minor improvements. If you are
interested in seeing the 2 files I could send them by email.

Fraser.
 
J

Jonathan Turkanis

Fraser Ross said:
I have made improvements to the igzstream and ogzstream classes available
from the link to "zlib C++ wrapper" at the zlib home page. They fix a bug
with gzstreambuf::close() as well as mainly minor improvements. If you are
interested in seeing the 2 files I could send them by email.

I'm sure the authors of the C++ wrapper would be interested. I don't use it in
my library.

Thanks,
Jonathan
 
F

Fraser Ross

You have missed the lhs parameter with the operator<<. Thats probably a
typo.

If you try other manipulators and member functions the tee_streem member
functions and related globals have to be extended. I.e. dec, setf, setfill
etc.

Fraser.
 
T

Tommi =?UTF-8?B?TcOka2l0YWxv?=

Fraser Ross said:
My program outputs to cout and I want it to output to a LOG file as well.
Is there a simple way to do that?

Fraser.

Hi I have a class tee in my toolbox for this. I attach the header and cpp
here.

The solution is to implement a streambuf, which passes everything to 2 other
streambufs and a ostream, which uses this streambuf.

You use it like this:

std::eek:fstream logfile("logfile.log");
tee my_stream(logfile, std::cout);
my_stream << "put this message ito logfile.log and console" << std::endl;

the second stream defaults to std::cout (just like /usr/bin/tee in unix), so
it is enough to declare:

tee my_stream(logfile);


Tommi Mäkitalo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top