web-dev-qa-db-ja.com

C ++またはライブラリにnull std :: ostream実装がありますか?

std::ostreamのように機能する/dev/null実装を探しています。ストリーミングされたものはすべて無視されます。そのようなものは標準ライブラリまたはBoostに存在しますか?それとも自分で巻かなければなりませんか?

52
paperjam

ブーストがある場合は、null ostream&istreamの実装がboost/iostreams/device/null.hppにあります。その要点:

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

最も簡単な解決策は、未開封のstd::ofstream。これはストリームでエラー状態になりますが、ほとんどの出力者はこれをチェックしません。通常のイディオムは、終了後にチェックを最後まで残すことです(これにより、作成したコードに入れられ、ストリームが無効であることを確認できます)。

それ以外の場合は、実装が非常に簡単です。小さなバッファを含むstreambufを作成し、overflowに設定するだけです(常に成功を返します)。ただし、これは開いていないファイルよりも遅くなることに注意してください。さまざまな >>演算子は引き続きすべての変換を行います(ストリームにエラー状態がある場合は行われません)。

編集:

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;
    }
};

通常、istreamまたはostreamから派生した便利なクラスも提供します。これには、使用するこのバッファーのインスタンスが含まれます。以下に沿ったもの:

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

または、std::ostream、streambufのアドレスを渡します。

26
James Kanze

ストリームにbadbitを設定すると、何も出力されません。

#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";
}

出力:

a
c
17

私はこれが非常に古いスレッドであることを知っていますが、ブーストなしで最速の同じソリューションを探しているすべての人にこれを追加したいと思います。

上記の3つの異なる提案と1つを/ dev/nullに直接書き込むことを組み合わせました(そのため、カーネルが関係しています)。

驚いたことに、最も多くの票を獲得したNullStreamが最悪のパフォーマンスを示しました。

以下は、100,000,000回の書き込みの結果です。

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)

これがテストコードです

#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;
}

[〜#〜]編集[〜#〜]

最速のソリューション-私たちがbadbitを使用している場合-にはマイナス面があります。プログラムが出力が正常に書き込まれたかどうかをチェックし、プログラムがそれを行わない理由がわからない場合は、このbadbitが原因で失敗します。したがって、準優勝者-boost-が勝者です。

8
Grzegorz

私にとっては、最も簡単な方法は次のとおりです。

#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;
}

または、上記の「nullstream」関数で「/ dev/null」の代わりに「badbit」フラグを使用します。

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;
}
0
user1317490

このソリューションが、ブーストを使用せずにパフォーマンスの問題を克服できるように:

#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){}
};
0
Karsten