自定义流到 C++ 中的方法?

2022-01-07 00:00:00 stream c++

我正在制作一个记录器,我希望有一些类似流的事情发生,理想情况下做 CLogger <<测试",<<1<<",2,3 "; 而不是 CLogger->log("Testing, %i,2,3", 1);

I'm making a logger and I wish to have some kind of stream-like happenings going on, ideally doing CLogger << "Testing, " << 1 << ",2,3 "; instead of CLogger->log("Testing, %i,2,3", 1);

我的问题是我该怎么做?我不想直接创建一个到 stdout 的流,因为我想使用我自己的方法,包括写入文件等.我已经考虑过重载一个特定的结构,它将当前的流缓冲区刷新到一个方法,但我必须做 CLogger <<冲洗<<"Test! "; 这有点奇怪.

My question is how would I do this? I don't want to directly create a stream to stdout as I want to use my own method which includes writing files and such. I've considered overloading with a certain struct that'd flush the current stream buffer to a method, but I'd have to do CLogger << flush << "Test! "; which is kind of odd.

有人知道怎么做吗?

推荐答案

如果您需要的只是将某些日志消息定向到文件,您是否考虑过 std::ofstream?

If all that you need is directing certain log messages to files, have you considered std::ofstream?

否则,我喜欢从 std::ostream 派生我的日志记录类,所以我得到了流的所有优点.诀窍是将所有特定于应用程序的代码放在关联的 streambuf 类中.考虑:

Otherwise, I like to derive my logging class from std::ostream, so I get all of the stream goodness. The trick is to put all of your application-specific code in the associated streambuf class. Consider:

#include <iostream>
#include <sstream>

class CLogger : public std::ostream {
private:
    class CLogBuf : public std::stringbuf {
    private:
        // or whatever you need for your application
        std::string m_marker;
    public:
        CLogBuf(const std::string& marker) : m_marker(marker) { }
        ~CLogBuf() {  pubsync(); }
        int sync() {
            std::cout << m_marker << ": " << str();
            str("");
            return std::cout?0:-1;
        }

    };

public:
    // Other constructors could specify filename, etc
    // just remember to pass whatever you need to CLogBuf
    CLogger(const std::string& marker) : std::ostream(new CLogBuf(marker)) {}
    ~CLogger() { delete rdbuf(); }
};

int main()
{
    CLogger hi("hello");
    CLogger bye("goodbye");

    hi << "hello, world" << std::endl;
    hi << "Oops, forgot to flush.
";
    bye << "goodbye, cruel world
" << std::flush;
    bye << "Cough, cough.
";
}

注意事项:

  • CLogger 构造函数可以采用您需要使用的任何参数――文件名、输出语言、指向底层日志数据的指针,等等.只需将数据传递到 CLogBuf 类即可.
  • CLogBuf 的 sync() 在响应 std::flush 期间被自动调用.

相关文章