</pre><p>因获取当前软件名字和使用互斥锁用了qt的头文件,如不想支持qt,可改成给定文件名,互斥锁可换成windows下或者linux下的互斥锁,或者boost库的锁也行。多线程下写日志会否出现错乱暂未测试,如不能正常工作,可用锁把vsprintf部分和写文件部分锁起来,应该不会再出问题。
log.h头文件内容如下:
#ifndef LOG_H
#define LOG_H
#include <QMutex>
typedef enum
{
LOG_EMER = 0,
LOG_ERR,
LOG_WAN,
LOG_INFO,
LOG_DEBUG
}LogLevel;
class Log
{
public:
Log(const std::string& filepath, const std::string &name ="");
~Log();
static Log* Instance();
void WrLog(LogLevel level, const char* fmt, ...);
void SetLogLevel(LogLevel level){ m_level = level;}
private:
Log(const Log& log);
Log& operator=(const Log& log);
private:
FILE *m_file;
LogLevel m_level;
static Log* m_Instace;
static QMutex m_mutex;
};
void WriteLog(const char* file, const char* fun, int line, LogLevel level, const char* fmt,...);
#define WLog(level,fmt,...) WriteLog(__FILE__,__FUNCTION__,__LINE__,level,fmt,##__VA_ARGS__)
#endif // LOG_H
log.cpp文件内容如下:
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span><pre class="cpp" name="code">#include <QCoreApplication>
#include <QMutexLocker>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <direct.h>
#include <string>
#include <time.h>
#include "log.h"
const char* LevelToStr(LogLevel level)
{
switch (level) {
case LOG_DEBUG:
return "DEB";
break;
case LOG_INFO:
return "INF";
break;
case LOG_WAN:
return "WAN";
break;
case LOG_ERR:
return "ERR";
break;
case LOG_EMER:
return "EME";
break;
default:
return "DEB";
break;
}
}
void WriteLog(const char* /*file*/, const char *fun, int /*line*/, LogLevel level,const char* fmt,...)
{
time_t t = time(NULL);
tm* tt = localtime(&t);
char tdata[32] = {0};
sprintf(tdata,"%d/%d/%d %d:%d:%d",tt->tm_year+1900,tt->tm_mon+1,tt->tm_mday,
tt->tm_hour,tt->tm_min,tt->tm_sec);
const int size = 1024*8;
char buf[size] = {0};
va_list args;
va_start(args,fmt);
vsprintf(buf,fmt,args);
// vsprintf_s(buf,size,fmt,args);
va_end(args);
Log::Instance()->WrLog(level,"[%s][%s][%s]%s\n",tdata,LevelToStr(level),fun,buf);
}
Log* Log::m_Instace = NULL;
QMutex Log::m_mutex;
Log::Log(const std::string &filepath, const std::string &name)
{
m_level = LOG_DEBUG;
m_file = fopen(filepath.c_str(),"a+");
if(m_file == NULL)
{
const char *path = "./log";
if(0 != access(path,F_OK)) // 判断路径是否存在
{
mkdir(path);
std::string::size_type pos = filepath.rfind("/");
std::string fileName;
if(pos != std::string::npos)
{
fileName = filepath.substr(pos);
fileName = std::string(path)+fileName;
}
else
{
fileName = std::string(path) + "/" + name;
}
m_file = fopen(fileName.c_str(),"w+");
}
else
{
m_file = fopen(filepath.c_str(),"w+");
}
}
}
Log::~Log()
{
if(m_file != NULL)
{
fclose(m_file);
}
}
void Log::WrLog(LogLevel level, const char* fmt, ...)
{
if(m_file == NULL)
{
printf("m_file == NULL\n");
qDebug("m_file == NULL\n");
return;
}
const int size = 1024*8;
char buf[size] = {0};
va_list va;
va_start(va,fmt);
//vsprintf_s(buf,size,fmt,va);
vsprintf(buf,fmt,va);
va_end(va);
printf("%s\n",buf);
qDebug("%s\n",buf);
// 级别低于当前级别,则不输出到文件
if(level > m_level) return;
fwrite(buf,strlen(buf),1,m_file);
fflush(m_file);
}
Log* Log::Instance()
{
if(m_Instace == NULL)
{
QMutexLocker lock(&m_mutex);
if(m_Instace == NULL)
{
const std::string name = QCoreApplication::applicationName().toStdString();
const std::string appName = std::string("./log/") + name + std::string(".log");
m_Instace = new Log(appName);
}
}
return m_Instace;
}