c++ - 重定向和时间戳 std::cout

标签 c++ iostream

我需要将一个 ofstream 重定向到一个文件并为打印的每一行加上时间戳。 (它是日志系统的一部分)。

我有一个工作类设法做到这一点,但它拒绝在发出 std::endl 时刷新文件。我很感激任何帮助。 (如果有更简单的方法,请告知)。

#include <iostream>
#include <streambuf>
#include <fstream>
#include <sys/time.h>
#include <cstring>
#include <memory>

class TimeStampBuf: public std::streambuf {
public:
    explicit TimeStampBuf(std::streambuf* dest) :
            _dest(dest),
            _isAtStartOfLine(true),
            _owner( NULL) {
    }
    explicit TimeStampBuf(std::ostream& dest) :
            _dest(dest.rdbuf()),
            _isAtStartOfLine(true),
            _owner(&dest) {
        _owner->rdbuf(this);
    }
    virtual ~TimeStampBuf() {
        if (_owner != NULL) {
            _owner->rdbuf(_dest);
        }
    }
protected:
    virtual int overflow(int ch) {
        if (_isAtStartOfLine) {
            char timebuff[30];
            timeval curTime;
            gettimeofday(&curTime, NULL);
            strftime(timebuff, sizeof(timebuff), "%Y-%m-%d %H:%M:%S:",
                    localtime(&curTime.tv_sec));
            sprintf(timebuff + strlen(timebuff), "%03u\t",
                    (unsigned int) curTime.tv_usec / 1000);
            _dest->sputn(timebuff, strlen(timebuff));
        }
        _isAtStartOfLine = ch == '\n';
        return _dest->sputc(ch);
    }
private:
    std::streambuf *_dest;
    bool _isAtStartOfLine;
    std::ostream *_owner;
};
class OutputRedirectAndStamp {
public:
    OutputRedirectAndStamp(std::string file, std::ostream &s = std::cout, std::ios::openmode mode = std::ios::out){
        _s=&s;
        _file=file;
        if(_file.size()){
            _mode=mode;
            _buf.open(file.c_str(),mode);
            _coutBuf = s.rdbuf((std::streambuf*)&_buf);
        }
        _tsb.reset(new TimeStampBuf(s));
    }
    void reopen(void){
        _tsb.reset();
        if(_file.size()){
            _s->rdbuf(_coutBuf); //reset to previous output
            _buf.close();
            _buf.open(_file.c_str(),_mode);
            _coutBuf = _s->rdbuf((std::streambuf*)&_buf);
        }
        _tsb.reset(new TimeStampBuf(*_s));
    }
    ~OutputRedirectAndStamp() {
        _tsb.reset();
        if(_file.size()){
            _s->rdbuf(_coutBuf); //reset to previous output
        }
    }
private:
    std::string _file;
    std::ios::openmode _mode;
    std::ostream *_s;
    std::filebuf _buf;
    std::streambuf *_coutBuf;
    std::unique_ptr<TimeStampBuf> _tsb;
};
int main()    //example main
{
    std::unique_ptr<OutputRedirectAndStamp> a;
    a.reset(new OutputRedirectAndStamp("test.txt",std::cout,std::ios::app | std::ios::out));

    std::cout<<"this is written to file"<<2<<std::endl;
    a->reopen();
    std::cout<<"this is written to file also"<<std::endl;
    a.reset();
    std::cout<<"this is written to stdout"<<std::endl;
    return 0;
}

最佳答案

当您刷新 std::ostream 时,流缓冲区的 pubsync() 被调用,后者又调用 virtual 函数 同步()。如果您不覆盖 sync(),它只会通过返回 0 来声明它已成功。从你的 sync() 覆盖你应该只调用保持流缓冲区的 pubsync():

int TimeStampBuf::sync() {
    return _dest->pubsync();
}

关于c++ - 重定向和时间戳 std::cout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19305656/

相关文章:

C++ 如何用 std::string 格式化 float ?

c++ - Xcode 从我的主文件夹而不是资源加载程序资源 - C++

c++ - C++0x 中的完美转发是否会使 reference_wrapper 被弃用?

c++ - 为什么 istream_iterator<string>(ifstream ("test.txt")) 会导致错误?

c++ - 什么是 C++ iostream endl 惨败?

c++ - 在 C++ 中设置 double 会给出奇怪的数字

c++ - 使用 GCC 和 C++11 实现类型 "long double"

c++ - 链表函数cpp中的指针作用域

c++ - IAudioSessionNotification,有人有工作代码吗?

c++ - Pstreams - 如何写入标准输入并获取输出?