Дата в файле журнала с использованием ofstream

Ниже приведен код, который я должен писать каждый раз, когда я хочу включить дату в мой файл журнала в данный момент. Я ищу способ не писать 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;

Нужно ли писать класс журнала и оператор перегрузки<< или есть другой способ сделать это?

1 ответ

Решение

Способ реализации потока, который автоматически добавляет (или удаляет) символы, например, добавляет дату, заключается в создании буфера фильтрующего потока. Вы бы получили класс от 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 << "hello\nwordl\n";
    logout << "\n";
    logout << "goodbye\n";
}
Другие вопросы по тегам