Copy all std::cout messages to log file? [duplicate] - c++

I need redirect the copy of std::cout to the file. I.e. I need see the output in console, and in file. If I use this:
// redirecting cout's output
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("c:\\temp\\test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
cout.rdbuf(backup); // restore cout's original streambuf
filestr.close();
return 0;
}
then I write string to the file, but I see the nothing in console. How can I do it?

The simplest you can do is create an output stream class that does this:
#include <iostream>
#include <fstream>
class my_ostream
{
public:
my_ostream() : my_fstream("some_file.txt") {}; // check if opening file succeeded!!
// for regular output of variables and stuff
template<typename T> my_ostream& operator<<(const T& something)
{
std::cout << something;
my_fstream << something;
return *this;
}
// for manipulators like std::endl
typedef std::ostream& (*stream_function)(std::ostream&);
my_ostream& operator<<(stream_function func)
{
func(std::cout);
func(my_fstream);
return *this;
}
private:
std::ofstream my_fstream;
};
See this ideone link for this code in action: http://ideone.com/T5Cy1M
I can't currently check if the file output is done correctly though it shouldn't be a problem.

You could also use boost::iostreams::tee_device. See C++ "hello world" Boost tee example program for an example.

Your code does not work, because it is the streambuf that determines where the output written to a stream end up, not the stream itself.
C++ does not have any streams or streambufs that support directing the output to multiple destinations, but you could write one yourself.

Related

overwrite file only at the first actual write

I would like to open a file for writing, such that the file is wiped and written over at the first write instruction. That is, the file should retain its contents when opened, and only at the first insertion is actually written over.
Using std::fstream, if I use the mode std::ios_base::out, the file is immediately wiped as soon as the constructor is called
#include <fstream>
int main()
{
std::fstream f("test.txt", std::ios_base::out);
// Now test.txt is empty
f << "hello";
}
This behavior would be ok if test.txt does not exists. But if test.txt exists, I would like to have its contents preserved until I write to it. If I open it with
std::fstream f("test.txt", std::ios_base::out | std::ios_base::in);
indeed an existing file is still preserved, and it is written over only on f << "hello".
However, if the file exists and contains more data then the string "hello", then f << "hello" will only overwrite the first 5 characters. I would like the file to be wiped, as if it were opened with std::ios_base::out, but only when I execute f << "hello".
Context
The problem arises with a routine like this:
void do_something(std::ostream& s)
{
//... very long computation
s << "some infos" << std::endl;
}
I call do_something passing to it a stream, which could or could not be a file. If it is a file, I would like to be able to inspect test.txt before the computation is done.
One possibility could be to wrap a fstream in a new object that actually opens the file only when operator<< is called, something like
#include <fstream>
class myfstream {
std::fstream m_f;
std::string m_filename;
public:
myfstream(std::string& filename) : m_filename{filename} { }
template <typename U>
myfstream& operator<<(const U& s) { if (!m_f.is_open()) m_f.open(m_filename, std::ios_base::out); m_f << s; return *this; }
};
The drawback of this solution is the lack of flexibility: if the routine do_something does something else than just calling operator<<, one has to define all the other members of std::ostream, to mimick its behavior. Also, to retain flexibility do_something has to be declared as
template <typename S>
void do_something(S& o);
Is there a better solution? Would it be possible, say, given a fstream to delete all data after the current position of the output indicator?
Update
Apparently, a possible solution is to get the actual write position with tellp() and after closing the file, resize it. See following code:
#include <fstream>
#include <filesystem>
#include <iostream>
int main()
{
typename std::fstream::pos_type size;
{
char d;
std::fstream f("test.txt", std::ios_base::in | std::ios_base::out);
std::cin >> d; // Just to pause
f << "hello";
size = f.tellp();
}
char d;
std::cin >> d; // Just to pause
std::filesystem::resize_file("test.txt", size);
return 0;
}
(The std::cin are there only to pause and be able to check the actual contents of the file).
Testing the program, after the first "pause" the file is still intact. After the second pause, the first characters have been overwritten with the string "hello", but any text following that is still untouched. Finally, resize_file shrinks the file to the actual length of the written string.
The above code does an implicit conversion between a pos_type as returned from tellp() and a std::uintmax_t as required from resize_file.
Is this conversion safe?

Redirect debug output to null stream instead of std::cerr

A software library that I am working with writes a lot of debug output to std::cerr, but redirects that output to a null stream if I tell it to be quiet. This is a simplified main.cpp that shows how the code tries to achieve this:
#include <iostream>
#include <fstream>
#include <cassert>
// The stream that debug output is sent to. By default
// this points to std::cerr.
std::ostream* debugStream(&std::cerr);
// Throughout the library's codebase this function is called
// to get the stream that debug output should be sent to.
std::ostream& DebugStream()
{
return *debugStream;
}
// Null stream. This file stream will never be opened and acts
// as a null stream for DebugStream().
std::ofstream nullStream;
// Redirects debug output to the null stream
void BeQuiet()
{
debugStream = &nullStream;
}
int main(int argc, char** argv)
{
DebugStream() << "foo" << std::endl;
BeQuiet();
DebugStream() << "bar" << std::endl;
assert(debugStream->good());
return 0;
}
When you run this program, you will notice that the string "bar" is correctly sent to the null stream. However, I noticed that the assertion fails. Is this something that I should be concerned about? Or is this just a slightly ugly detail of the approach chosen by the library developers?
If you feel like it, suggestions for better alternatives are welcome. Some constraints:
The library is cross-platform, so I think using opening /dev/null is not a valid solution as it would not work on Windows
The library uses standard C++, so any alternative solutions should not use compiler-specific stuff
There is no real need to be worried about the stream not being good()! Since the output operators don't really do anything wirh a stream in failure mode the different entities being logged are not formatted, i.e., the code does run faster compared to alternative approaches.
Note that you don't really need a second stream to disable output:
Assuming all output operators are well-behaved, you can just set std::ios_base::failbit:
debugStream().setstate(std::ios_base::failbit);
If there are misbehaved output which write to a stream even if it isn't good() you can just set its stream buffer to null:
debugStream().rdbuf(nullptr);
If you really want your stream to remain in good() state, you'd install a stream buffer which just consumes characters. Note, however, that you want to give this stream buffer a buffer as having overflow() called for each char is fairly exensive:
struct nullbuf
: std::streambuf {
char buf[256];
int overflow(int c) {
this->setp(this->buf, this->buf + 256);
return std::char_traits<char>::not_eof(c);
}
};
...
nullbuf sbuf;
debugStream().rdbuf(&sbuf);
...
debugStream().rdbuf(0);
It is necessary to reset the stream's stream buffer because the destructor of an std::ostream will flush the stresm buffer (i.e., it calls pubsync()). Doing so on a destroyed stream buffer won't work.
Personally, I would go with setting std::ios_base::failbit.
In this answer you find a general helper to redirect any stream to any other stream:
class stream_redirector {
public:
stream_redirector(std::ios& stream, std::streambuf* newBuf) :
savedBuf_(stream.rdbuf()), stream_(stream)
{
stream_.rdbuf(newBuf);
}
~stream_redirector() {
stream_.rdbuf(savedBuf_);
}
private:
std::streambuf* savedBuf_;
std::ios& stream_;
};
and now all you need is a no-op stream from this answer which discards anything:
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
// note: the original code is missing the required this->
this->init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
and you're good to go:
int main(int argc, char** argv)
{
std::cerr << "foo" << std::endl;
{
onullstream nos;
stream_redirector sr( std::cerr, nos.rdbuf() );
std::cerr << "bar" << std::endl;
}
std::cerr << "baz" << std::endl;
}
and finally here's a live example in case you want to play with it. This method has the additional benefit that you (and your colleagues) can still use std::cerr in your code and you can turn it off and on again at will :)

C++ ostream and ofstream conversions

My code has an ostream object that is accumulated by various modules and ultimately displayed to the console. I'd like ALSO to write this ostreamobject to a file, but do I have to rewrite all of that code using an ofstream object instead, or is there a way to convert one to the other (perhaps via a stringstream?)
For example, many of my existing functions look like
ostream& ClassObject::output(ostream& os) const
{
os << "Details";
return os;
}
Can I call this function with an ofstream object as the argument and have that ofstream object accumulate information instead?
Yes, you can. That's the point in the OO concept called subtype polymorphism. Since ofstream derives from ostream, every instance of ofstream is at the same time an instance of ostream too (conceptually). So you can use it wherever an instance of ostream is expected.
ofstream derived from ostream so
Just add some code in main.cpp
#include "ClassObject"
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ClassObject ob;
cout << ob; // print info to console window
// save info to .txt file
ofstream fileout;
fileout.open("filename.txt", ios::app);
fileout << ob;
fileout.close();
return 0;
}

how to redirect ostream object to a temporary buffer?

I have a C++ code that has a lot of functions which receives ostream as argument. I wanted to unit test those functions, for that I have to verify ostream object data after execution to the function. I can redirect output stream to a file but I wanted to check if I can create a temporary buffer and redirect the output stream to the buffer and read from that buffer.
You can use std::stringstream as an in memory std::ostream:
#include <iosfwd>
#include <sstream>
#include <cassert>
void my_func(std::ostream& out) {
out << "test";
}
int main() {
std::ostringstream buf;
my_func(buf);
assert(buf.str() == "test");
}

operator overloading

How can I overload << operator (cout) so that it can be written to a file. Whenever << occurs it should be appended to the file i.e. instead of displaying on the screen it should be written to the file.
can i get a code for this...i am new to c++ and code written by me is not working..
Normally you provide std::ostream& operator<<(std::ostream&, const YourClass&) for your class and write to a file stream as follows:
std::ofstream ofs("out");
ofs << yourObject;
where yourObject is an object of YourClass.
Your overloaded << operator shouldn't care what kind of output stream that it goes to or whether it's appending or overwriting. It takes a std::ostream& and writes to it. If it's used with cout, then it's written to the console. If it's used with a std::ofstream, then it writes to a file. If that std::ofstream was opened to overwrite, then it overwrites. If it was opened to append, then it appends.
All that your overloaded << operator should care about is that it's writing to an output stream. What that stream represents is irrelevant.
This overloading is already done for the C++ file stream. The name cout means console out and the spirit is, it will output to console.
One thing you could do is use freopen(), to redirect all output to a file.
If you just want to send text to a file rather than the console, then std::ofstream is your friend. Like cout, your instance of ofstream shares the behaviour of ostream which already has a suitable << operator for strings and can be used exactly as cout. Here's an example:
#include <fstream>
int main()
{
std::ofstream fout("somefile.txt");
fout << "Some text" << std::endl;
return EXIT_SUCCESS;
}
Compile and run and you'll find that you have a new file in the current working directory:
% cat somefile.txt
Some text
If you need to stream an object that doesn't have operator << overloaded for std::ostream, then you you will need to overload the operator, like this:
std::ostream& operator <<(std::ostream& os, const SomeClass& instance)
{
instance.print(os);
return os;
}
You'll need void SomeClass::print(std::ostream& os) defined to send its private data to os (this saves you making the << a friend of your class).
Were you talking purely about cout, then this isn't "operator overloading", this is stream redirection. But, yes, it is possible (too) by setting the associated stream buffer using std::basic_ios::rdbuf().
Here is my solution from "Redirecting in C++":
#include <iostream>
#include <fstream>
class scoped_cout_redirector
{
public:
scoped_cout_redirector(const std::string& filename)
:backup_(std::cout.rdbuf())
,filestr_(filename.c_str())
,sbuf_(filestr_.rdbuf())
{
std::cout.rdbuf(sbuf_);
}
~scoped_cout_redirector()
{
std::cout.rdbuf(backup_);
}
private:
scoped_cout_redirector();
scoped_cout_redirector(const scoped_cout_redirector& copy);
scoped_cout_redirector& operator =(const scoped_cout_redirector& assign);
std::streambuf* backup_;
std::ofstream filestr_;
std::streambuf* sbuf_;
};
int main()
{
{
scoped_cout_redirector file1("file1.txt");
std::cout << "This is written to the first file." << std::endl;
}
std::cout << "This is written to stdout." << std::endl;
{
scoped_cout_redirector file2("file2.txt");
std::cout << "This is written to the second file." << std::endl;
}
return 0;
}