日志文件中的日期使用 ofstream

Date in log file using ofstream

本文关键字:ofstream 日期 文件 日志      更新时间:2023-10-16

下面是我每次想在日志文件中包含日期时必须编写的代码。我正在寻找一种方法,不必每次想在文件中写入内容时都不必写我的CurrentDateToString()

ofstream log;
log.open("test.log", ios_base::app);
log << CurrentDateToString() << " | " << "first line" << endl;
log << CurrentDateToString() << " | " << "second line" << endl;
log.close();

这是我的CurrentDateToString()函数:

// convert date to formatted string
string CurrentDateToString()
{  
    time_t rawtime;
    struct tm* timeInfo;
    char buffer[80];
    time(&rawtime);
    timeInfo = localtime(&rawtime);
    strftime(buffer, 80, "%Y-%m-%d %I:%M:%S", timeInfo);
    string dateString(buffer);
    return dateString;
}

这里的目标是能够写这些行,而不是我正在写的当前行:

log << "first line" << endl;
log << "second line" << endl;

我是否必须编写日志类和重载运算符<<或者有其他方法可以做到这一点?

实现自动添加(或删除)字符(例如添加日期)的流的方法是创建一个过滤流缓冲区。您将从std::streambuf派生一个类,该类将收到的字符调整为必要的形式,然后将它们转发到基础流缓冲区。

对于在行首添加日期的使用,您只需观察收到的换行符,并在need_date有换行符时设置标志。在设置字符时写入字符need_date时,将写入日期并清除标志。

以下是寻找您的约会对象的方法:

#include <streambuf>
class logbuf
    : public std::streambuf {
    std::streambuf* sbuf;
    bool            need_date{true};
    using traits_type = std::char_traits<char>;
    int overflow(int c) override {
        if (c != traits_type::eof()) {
            if (need_date) {
                std::string date{CurrentDateToString()};
                this->sbuf->sputn(date.c_str(), date.size());
                need_date = false;
            }
            if (c == 'n') {
                need_date = true;
            }
            return this->sbuf->sputc(c);
        }
        else {
            return traits_type::not_eof(c);
        }
    }
    int sync() override { return this->sbuf->pubsync(); }
public:
    logbuf(std::streambuf* sbuf): sbuf(sbuf) {}
};

每次流缓冲区的缓冲区中没有空间时,都会调用 virtual 函数 overflow()。由于没有为每个字符设置输出缓冲区(可以通过添加xsputn()覆盖和/或添加缓冲来提高性能)。每次刷新流时都会调用函数 sync()。由于没有缓冲任何内容,因此刷新请求只是转发到基础流缓冲区。

下面是使用此流缓冲区的简单演示。创建一个合适的底层流缓冲区,例如,一个std::filebuf,和一个std::ostream可以打包到一个派生自std::ostream的类中。

#include <iostream>
int main()
{
    logbuf sbuf(std::cout.rdbuf());
    std::ostream logout(&sbuf);
    logout << "hellonwordln";
    logout << "n";
    logout << "goodbyen";
}