Error with ostream definition - c++

Doing some refactoring, I get an error after moving some code in a class' member function:
std::ostream logStream; // <-- error
std::filebuf fileBuffer;
// Send the output either to cout or to a file
if(sendToCout) {
logStream.rdbuf(std::cout.rdbuf());
}
else {
fileBuffer.open("out.txt", std::ios_base::out | std::ofstream::app);
logStream.rdbuf(&fileBuffer);
}
logStream << "abcd..." << std::endl;
This is the compiler error message:
file.cpp:417: error: calling a protected constructor of class 'std::__1::basic_ostream<char>'
std::ostream logStream;
^
Could this be a solution?
std::filebuf fileBuffer;
std::ostream logStream(&fileBuffer);
...
if(sendToCout) {
logStream.rdbuf(std::cout.rdbuf());
}

If you see e.g. this std::ostream constructor reference you will see that the only public constructor is one taking a pointer to a std::streambuf object, like for example your variable fileBuffer.
So one way to solve your problem is to do
std::filebuf fileBuffer;
std::ostream logStream(&fileBuffer);
A better solution is to use std::ofstream if you want output to a file.
If you want a more generic solution, where it should be possible to use any kind of output stream, then a redesign to use references instead is a possible solution.
Or, you know, try and find an existing logging library which handles everything for you already.

Related

Using my own String class with the << operator

I am looking for a way to use an ostream with my custom string class and overload the operator << to stream to the buffer which i can then flush to anywhere i want (in my case its just gonna be printed in a window)
I'm reasonably new to the inner workings of iostream's but from my understanding the method i've seen of making std::stringbuf a base of my custom stringstream would not work because the stringbuf deals with the std::string.
in essence i want to able to do this (or similar):
MyStringClass string
MyOutput << "hello" << string << "World" << std::endl;
Where MyOutput can be changed to print to anywhere i want.
Thank you.
Not a problem. Define your class, and within it's definition add an ostream& operator<<(const String&);.
Inside that operator, you can code whatever handling you want (look at std::string for inspiration)

Detour cout to custom function

I have made a pretty big program which prints very much information to the screen all the time.
The thing is that I can't be there all the time to read and eventually spot errors. So I came up with the idea to write everything that is printed by cout to a file.
The problem is that, how I already wrote, there are plenty "cout's". Working through the whole code and replacing every cout by a custom function would be very annoying.
Is there a way I how I can "hook" cout to be redirected to a custom function of mine?
You can provide a custom stream buffer via the rdbuf method. Here's an example that redirects cout to a file:
std::ofstream ofs("output");
std::cout.rdbuf(ofs.rdbuf());
You can redirect standard output directly to to file using command line with output redirection
fileneame.exe > log.txt
or
./filename > log.txt
Else use some RAII, something like following:
class Logger
{
std::ofstream filehandle;
std::ostream& myStream;
std::streambuf* mySavedStreambuf;
public:
Logger( std::ostream& oldStream, std::string const& filename)
: filehandle(filename)
, myStream(oldStream)
, mySavedStreambuf(oldStream.rdbuf())
{
oldStream.rdbuf(filehandle.rdbuf());
}
~Logger()
{
myStream.rdbuf(mySavedStreambuf);
}
};
And then in your intilization/main routine do something like:
int main()
{
{
Logger temp( std::cout, "log.txt" );
// call funcs that has std::cout, all outputs will be in log.txt
}// temp goes out of scope, std::cout restored.
// Call funcs that has std::cout, now all outputs on standard ouput.
}

How to redirect stderr/stdout to my log in c++? [duplicate]

This question already has answers here:
Suppress output to cout from linked library
(6 answers)
Closed 7 years ago.
I'm using a 3rd party that sometimes has internal errors, when it happens the 3rd party writes to stderr and I can see it in the console.
(I do check the return values of the 3rd party functions and see that he's failed, but i want the information he writes to stderr)
I have a logger to whom I write using a method I have
SendLog(string log);
I want somehow to catch the things my 3rd party is writing to the stderr (maybe listen on the stderr some how) and then write this things to my log.
How can I do it ?
I need it because my users can't see the console, the only see the log.
It is important to note, my program doesn't crash or exists after those errors, it's continues to work.
EDIT:
My question is not the same as the allegedly similar question, I want to avoid using linker hacks (as been used in the similar question).
One solution is to duplicate everything that is written to cerr into for example a file.
This is the helper class:
class CTee {
public:
// Use ostream &s2 if you want to duplicate to an ostream, pass other
// stuff you need if you have other logging mechanisms.
CTee(ostream &s1, ostream &s2) : m_s1(s1), m_s1OrigBuf(s1.rdbuf()), m_teebuf(s1.rdbuf(), s2.rdbuf()) { s1.rdbuf(&m_teebuf); }
~CTee() { m_s1.rdbuf(m_s1OrigBuf); }
private:
CTee &operator =(CTee &rhs); // not implemented
class CTeeBuf : public streambuf {
public:
// Use streambuf *sb2 if you want to duplicate to an ostream/streambuf.
// Pass other Information if you want to log to something different.
CTeeBuf(streambuf* sb1, streambuf* sb2) : m_sb1(sb1), m_sb2(sb2) {}
protected:
virtual int_type overflow(int_type c) {
if(streambuf::traits_type::eq_int_type(c, streambuf::traits_type::eof()))
return c;
else {
// Put char to cerr/stream to duplicate
m_sb1->sputc((streambuf::char_type)c);
// Put char to duplicate stream. If you want to duplicate to something
// different, then write the char whereever you want to.
return m_sb2->sputc((streambuf::char_type)c);
}
}
virtual int sync() {
m_sb1->pubsync();
return m_sb2->pubsync();
}
// Store streambuf *m_sb2 if you want to duplicate to streambuf.
// Store anything else if you want to duplicate to something different.
streambuf *m_sb1, *m_sb2;
};
ostream &m_s1;
streambuf * const m_s1OrigBuf;
CTeeBuf m_teebuf;
};
CTee takes an ostream to duplicate and an ostream to duplicate to. It takes the ostream that shall be duplicated and replaces it's rdbuf, the streambuf that is written to, with a CTeeBuf (see CTee ctor). CTeeBuf takes the chars that are written to it and forwards them to the streambufs of both ostreams (see CTeeBuf::overflow and CTeeBuf::sync). The CTee dtor reverts the changed streambufs to their original values.
And it is used like this:
char logfilename[] = "myfile.log";
ofstream logfile(logfilename, ios_base::out | ios_base::app);
CTee tee(cerr, logfile);
From now on everything written to cerr will be duplicated to logfile (during the lifetime of tee). So this message will be written to cerr, but also to logfile:
cerr << "error occured: ..." << endl;
It is also possible to write to other ostreams than a logfile. If you don't want to duplicate to another ostream but to something else, just replace CTeeBuf::overflow by an implementation that logs whereever you want to.
See also http://www.cs.technion.ac.il/~imaman/programs/teestream.html and http://wordaligned.org/articles/cpp-streambufs.
One way is to use stringstream for this. If library write using c++streams that will work.
class redirect_stream
{
public:
redirect_stream(std::ostreamstream& stream, std::ostream& oldstream) :
stream_(stream), oldstream_(oldstream)
{
oldbuf_ = oldstream_.rdbuf();
oldstream_.rdbuf(stream_.rdbuf());
}
~redirect_stream()
{
const std::string str = stream_.str();
if (!str.empty())
{
SendLog(str);
}
oldstream_.rdbuf(oldbuf_);
}
private:
std::ostringstream& stream_;
std::ostream& olstream_;
std::streambuf* oldbuf_;
};
And before usage of 3rd party library just:
std::ostringstream oss;
redirect_stream redirecter(oss, std::cerr);
or you can not print message to log in destructor and just print oss.str() after the end of work with 3rd party library.
Simple usage example
You can use std::stringstream
std::stringstream log;
std::streambuf *buf = std::cerr.rdbuf(log).rdbuf());
std::cerr << "Error Msg" << std::endl;
std::string errMsg( log.str() );
errMsg will be "Error Msg".

read file and save in istream c++

I'm fairly new to C++ and I have this assignment to verify each line of a file.
I have to create a function with only one parameter(const std::istream& p_is)
My question is How can I read a file and save the buffer to a basic istream.
I found how to output it but I can't figure our how to save it in p_is
My code so far from an example I found on here
std::filebuf fb;
if (fb.open ("test.txt",std::ios::in))
{
std::istream File(&fb);
while (File)
std::cout << char(File.get());
fb.close();
}
This will output test.txt content in console perfectly
thanks in advance!
I think I understand now what you're trying to do. You can easily copy the contents of a buffer to another std::istream using the overload of operator<<() that takes a pointer to std::streambuf:
void copy_buf(std::istream& is)
{
if (std::ifstream in("test.txt"))
is << in.rdbuf(); /*
^^^^^^^^^^^^^^^^^ */
}
istream, as in input stream. You can't write to it. You either create a second stream to an output file (ostream), or create an append stream in the first place.
That said, I really, really doubt you read your assignment properly, your requirements make no sense.

Param syntax for substituting boost filtering_stream for std::ofstream

Some basic questions about boost filtering_streams. I have dozens of functions that take a parameter of std::ofstream&
void foo(std::ofstream& outStream)
{
// lots of operations, like this:
outStream << "various bits of text";
}
void StreamSomeTextToFile(char* fileName)
{
ofstream myFileStream(fileName, ios::out | ios::app | ios::binary);
foo(myFileStream);
myFileStream.close();
}
Now I'd like to use the boost filtering_stream to output to a compressed ZIP file. The commonly cited boost filtering_streams test code for packing and unpacking compiled, linked, and worked perfectly for me. I'd like to substitute the filtering_stream:
void StreamSomeCompressedTextToFile(char* fileName)
{
ofstream myFileStream(destPath, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> myCompressedFileStream;
myCompressedFileStream.push(boost::iostreams::zlib_compressor());
myCompressedFileStream.push(myFileStream);
foo(myCompressedFileStream); // I can't just pass myCompressedFileStream to foo(std::ofstream&), right?
myFileStream.close();
}
THREE QUESTIONS:
1) Do all my functions that previously accepted std::ofstream& outStream need to now accept a parameter of type boost::iostreams::filtering_streambuf& ? Or is there a proper parameter type so those numerous ("foo") functions could work with EITHER type of stream type?
2) In my simple test cases, I was not able to use stream operator syntax with the filtering_streambuf:
myCompressedFileStream << "some text";
this generated the the error: no match for 'operator<<'. I similarly had compile errors with write():
error: 'class boost::iostreams::filtering_streambuf<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>' has no member named 'write'
3) In the common test case example code (below), I was confused that I could not locate the file "hello.z" after it had been created. The unpack code (also below) clearly references it -- so where can it be found? NOTE: the location was finally discovered: it was in the /Library/Preferences/
void pack()
{
std::ofstream file("hello.z", std::ios_base::out | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::zlib_compressor());
out.push(file);
char data[5] = {'a', 'b', 'c', 'd', 'e'};
boost::iostreams::copy(boost::iostreams::basic_array_source<char>(data, sizeof(data)), out);
file.close();
}
void unpack()
{
std::fstream file("hello.z", std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
boost::iostreams::copy(in, std::cout);
}
BTW: XCode 3.2.6, GNU 4.0, OS X 10.6.8
Taking the questions in order:
1: Stream buffer objects (like boost::iostream::filtering_streambuf or std::streambuf) are not interchangeable with stream objects (such as std::ostream or boost's implementation). That being said, you can pass a streambuf object like "myCompressedFileStream" to a constructor of an ostream object (this boost iostream tutorial provides a decent explanation with examples). And because boost's streambufs are compatible with those in the standard library, you need not change any of the functions accepting std::ostream/ofstream references. You just can't pass streambufs as streams.
2: Same as above, the insertion operator is defined for streams, not streambufs.
3: Normally, files without a preceding directory name are created in the directory of the executable. That being said, I've found at times Finder has been somewhat slow reflect files updated/created by non-Finder processes. I didn't experience those problems in Terminal using ls. No idea if that's related to your problem, though.
SUCCESS!
A combination of hints from Paul Schellin (above) and several on Boost-users resulted in the answer:
1) Boost User Frédéric pointed out that "nothing happen[s] until output_file [filtering_ostream] is destroyed. So enclose in { }". This was the essential missing piece, because I was trying to do file.close() on my ofstream BEFORE my filtering_streambuf was destroyed. That explained why the file was empty!
Re-reading the documentation revealed:
"By default, if the Device at the end of the chain is popped
or if the filtering_stream is complete when it is destroyed,
all the filters and devices in the chain are closed using the
function close. This behavior can be modified using the member
function set_auto_close"
This states is there is no need to "pop" the compressor() or the ofstream (file) off the filtering_stream's stack, nor to call close(). Just destruct the filtering_stream object, and everything gets written out and cleaned up. An obscure detail, and one that goes counter to what one might expect.
3) Boost User Holger Gerth questioned why I was using filtering_streambuf when I could've been using filtering_stream. Truth is, I wasn't sure, however, in my experiments I could neither construct the ostream (which I required to pass to other functions) from the filtering_stream, nor could I pass the filtering_stream in place of the ostream I required.
Even after reading several articles on filtering_streambuf vs filtering_stream, I'm still mystified how and why (FOR MY PURPOSE) I would use the filtering_stream over constructing an ostream from a filtering_streambuf.
SO, TO RECAP:
1) Construct a separate ostream from the filtering_streambuf, and pass THAT to foo() or to the Stream Insertion operator (i.e. <<).
2) Don't call myFileStream.close();