c ++中的通用日志文件

时间:2016-12-20 06:13:10

标签: c++ file-handling

我正在尝试用c ++构建一个日志文件...任何人都可以告诉你如何将多个变量如字符串,整数写入文件......对代码文件部分的写入是用不同的函数编写的存在于链接到主文件的不同文件(例如log_file.h)中。

示例:

for(int i=0;i<3;i++)
{....}

我想将i的每个迭代值写入日志文件... 我可以通过在字符串中传递"value of i" - &gt;并"i" - &gt;来完成此操作作为一个整数...但这不适用于所有函数..

4 个答案:

答案 0 :(得分:1)

您可以实现printf之类的功能,该功能会使用variable argument list将参数记录到日志文件中。

#include <stdarg.h>     /* va_list, va_start, va_arg, va_end */

void logger(const char *_pcFormat, ...)
{
    char cszFilePath[] = "/var/tmp/mylog.txt";


    //assuming each log line will be less than equal to 2048 bytes.
    char cszLine[2048] = {0};

    //optional: you can even log the time, uncomment the following 2 lines, if required
    //time_t ulTime = time(NULL);
    //snprintf(cszLine, sizeof(cszLine), "%02d:%02d:%02d ", stTime.tm_hour, stTime.tm_min, stTime.tm_sec);

    va_list aptr;
    va_start(aptr, _pcFormat);
    char *pcLine = cszLine;
    vsprintf(pcLine + strlen(cszLine), _pcFormat, aptr);
    va_end(aptr);

    FILE *fp = fopen(cszFilePath, "a+");
    if(fp == NULL)
    {
            return;
    }

    fprintf(fp, "%s\n", cszLine);

    fclose(fp);
    fp = NULL;
} 

UPDATE_1:在此版本中,对行长度没有初步假设。

void logger(const char *_pcFormat, ...)
{
    char cszFilePath[] = "/var/tmp/mylog.txt";
    FILE *fp = fopen(cszFilePath, "a+");
    if(fp == NULL)
    {
            return;
    }        

    va_list aptr;
    va_start(aptr, _pcFormat);
    vfprintf(fp, _pcFormat, aptr);
    va_end(aptr);

    fclose(fp);
    fp = NULL;
}

答案 1 :(得分:1)

如果你想用C ++方式做,那么我认为你应该使用流和模板。如下所示:

#include <iostream>
#include <fstream>
#include <stdexcept>

class Logger
{
public:
    // Logger cannot exist without file.
    Logger() = delete;

    // Disable copy constructor  since std::ofstream is not copyable.
    Logger(Logger const&) = delete;

    // Constructor
    explicit Logger(std::string const& f_path)
        : log_file { f_path }
    {
        if (!log_file.is_open())
        {
            throw std::runtime_error("Unable to open log file");
        }
    }

    // Disable copy.
    Logger& operator=(Logger const&) = delete;

    // Cleanup.
    ~Logger()
    {
        log_file.close();
    }

    // Write a single value into log file stream.
    template<typename T>
    void write(T const& v)
    {
        log_file << v;
    }

    // Write multiple values.
    template<typename Arg, typename ...Args>
    void write(Arg const& arg, Args const&... args)
    {
        // here we write the first value of the values list.
        write(arg);
        // here we recursively pass the rest values to the function.
        write(args...);
    }
private:
    // Log file stream.
    std::ofstream log_file;
};

int main(int argc, char* argv[])
{
    Logger l { "test.log" };
    l.write(1);
    l.write("qwe", 34);
    return 0;
}

如您所见,记录器取决于std::ofstream。因此,如果您需要记录一些不受支持的类型,您只需要为它进行重载。 像这样:

// A custom type
struct MyType
{
    int id;
    std::string name;

    // an overload
    friend std::ofstream& operator<<(std::ofstream& ofs, MyType const& v)
    {
        ofs << "(" << v.id << ":" << v.name <<")";
    }
};

然后在main中使用它:

MyType person { 23, "John" };
l.write(person);

答案 2 :(得分:0)

您可以像这样定义日志方法

void Log(uint16_t level, const char * format, ...)

使用va_list,您可以格式化日志

char buffer[4096] = { 0 };
va_list argList;
va_start(argList, format);
vsprintf(buffer, format, argList);
va_end(argList);

现在buffer保存格式化的日志消息,您可以使用buffer写入文件,打印到控制台等

用法

for(int i=0; i<10; i++)
    Log(1, "%d iteration = %s", i, "hello");

在你的缓冲区中你会得到

0 iteration hello
1 iteration hello
....
9 iteration hello

使用级别来标识日志消息的类型

答案 3 :(得分:-1)

我不明白你的问题。对于日志文件,您可以使用类似这样的内容:

#include <fstream>
#include <string>
using namespace std;

string myString = "bla";

ofstream out;
out.open("myLog.dat"); // ios::app or ios::trunc, check it in the documentation what you need
if (out.is_open()) {
  for (int i = 0; i < I; i++) {
    out << i << "," << myString << endl;
    out << i*3 << endl;
  }
}
else
  throwError();

请说明您的问题。