Is there a null std::ostream implementation in C++ or libraries?

馋奶兔 提交于 2019-11-27 01:26:57

问题


I'm looking for a std::ostream implementation that acts like /dev/null. It would just ignore anything that is streamed to it. Does such a thing exist in the standard libraries or Boost? Or do I have to roll my own?


回答1:


If you have boost, then there's a null ostream & istream implementation available in boost/iostreams/device/null.hpp . The gist of it:

#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...



回答2:


The simplest solution is just to use an unopened std::ofstream. This will result in an error state in the stream, but most outputters won't check this; the usual idiom is to leave the check to the end, after the close (which would put it in code you wrote, where you know that the stream should be invalid).

Otherwise, it's pretty straight forward to implement: just create a streambuf which contains a small buffer, and sets it up in overflow (always returning success). Note that this will be slower than the unopened file, however; the various >> operators will still to all of the conversion (which they don't do if the stream has an error state).

EDIT:

class NulStreambuf : public std::streambuf
{
    char                dummyBuffer[ 64 ];
protected:
    virtual int         overflow( int c ) 
    {
        setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) );
        return (c == traits_type::eof()) ? '\0' : c;
    }
};

It's usual to provide a convenience class derived from istream or ostream as well, which will contain an instance of this buffer which it uses. Something along the lines of:

class NulOStream : private NulStreambuf, public std::ostream
{
public:
    NulOStream() : std::ostream( this ) {}
    NulStreambuf* rdbuf() const { return this; }
};

Or you can just use an std::ostream, passing the address of the streambuf to it.




回答3:


If you set badbit on a stream it won't output anything:

#include <iostream>

int main() {
    std::cout << "a\n";

    std::cout.setstate(std::ios_base::badbit);
    std::cout << "b\n";

    std::cout.clear();
    std::cout << "c\n";
}

Outputs:

a
c



回答4:


I know this is very old thread, but I would like to add this to anyone who is looking for the same solution without boost and the fastest one.

I combined three different proposals above and one writing directly to /dev/null (so it involves kernel.)

Surprisingly the NullStream that got the most votes performed the worst.

Here are results for 100,000,000 writes:

a) /dev/null : 30 seconds
b) NullStream: 50 seconds
c) badbit    : 16 seconds (the winner in speed, but cannot test for errors!)
d) boost     : 25 seconds (the ultimate winner)

Here is the test code

#include <iostream>
#include <fstream>
#include <time.h>
#include <boost/iostreams/stream.hpp>

class NullStream : public std::ostream {
    class NullBuffer : public std::streambuf {
    public:
        int overflow( int c ) { return c; }
    } m_nb;
public:
    NullStream() : std::ostream( &m_nb ) {}
};

int test( std::ostream& ofs, const char* who ) {
    const time_t t = time(NULL);
    for ( int i = 0 ; i < 1000000000 ; i++ )
        ofs << "Say the same" ;
    std::cout << who << ": " << time(NULL) - t << std::endl;
}

void devnull() {
    std::ofstream ofs;
    ofs.open( "/dev/null", std::ofstream::out | std::ofstream::app );
    test(ofs, __FUNCTION__);
    ofs.close();
}

void nullstream() {
    NullStream ofs;
    test(ofs, __FUNCTION__);
}

void badbit() {
    std::ofstream ofs;
    ofs.setstate(std::ios_base::badbit);
    test(ofs, __FUNCTION__);
}

void boostnull() {
    boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
    test(nullOstream, __FUNCTION__);
}

int main() {
    devnull();
    nullstream();
    badbit();
    boostnull();
    return 0;
}

EDIT

The fastest solution - where we use badbit - has a downside. If the program checks if the output is successfully written - and I have no idea why the program should not do that - then it will fail because of this badbit. Therefore, the runner up - boost - is the winner.




回答5:


As for me the simplest way would be:

#include <fstream>

std::ostream* out = &std::cout;

std::ostream* nullstream() {
    static std::ofstream os;
    if (!os.is_open())
        os.open("/dev/null", std::ofstream::out | std::ofstream::app);
    return &os;
}

int main() {
    *out << "Normal output\n";

    out = nullstream();
    *out << "Will not visible\n";

    out = &std::cout;
    *out << "Back again\n";

    return 0;
}

Or use 'badbit' flag instead of '/dev/null' in 'nullstream' function as described above.

std::ostream* nullstream() {
    static std::ofstream os;
    static bool flag_set = false;
    if (!flag_set) {
        os.setstate(std::ios_base::badbit);
        flag_set = true;
    }
    return &os;
}



回答6:


May this solution overcomes the performance issue without using boost:

#include <ostream>

class dev0_buffer : public std::streambuf
{
   //called usually for n-characters
   std::streamsize xsputn (const char* s, std::streamsize n) override { return n; }

   //may not required due it's not called anymore
   int overflow (int c)  override { return c; } 
} nirwana;

class dev0_stream : public std::ostream
{
   public:
    dev0_stream(): std::ostream(&nirwana){}
};


来源:https://stackoverflow.com/questions/8243743/is-there-a-null-stdostream-implementation-in-c-or-libraries

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!