logoutput.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "logoutput.h"
  2. #include <QFile>
  3. #include <QTextStream>
  4. #include <QDateTime>
  5. #include <QMutex>
  6. #include <QFileInfo>
  7. #include <QMetaEnum>
  8. #include <QSettings>
  9. #include <QDir>
  10. #include "config.h"
  11. extern config *pconfig;
  12. LogOutput * LogOutput::ins = nullptr;
  13. QMutex LogOutput::m_mutex;
  14. LogOutput::LogOutput(QObject *parent) : QObject(parent)
  15. {
  16. }
  17. LogOutput::~LogOutput()
  18. {
  19. if(m_curLogFile.isOpen())
  20. m_curLogFile.close();
  21. qInfo() << "日志输出模块释放";
  22. }
  23. //安装日志函数
  24. void LogOutput::install()
  25. {
  26. //创建log文件夹
  27. #ifdef Q_OS_WIN
  28. logPath = "./log/";
  29. #else
  30. logPath = pconfig->configpath + "log/";
  31. #endif
  32. QDir dir(logPath);
  33. if(!dir.exists())
  34. {
  35. dir.mkdir(logPath);
  36. qDebug() << logPath;
  37. qDebug() << QString("运行日志文件夹创建成功:%1").arg(logPath);
  38. }
  39. // 打开日志输出文件(不存在则创建并打开)
  40. openTheLogFile();
  41. //安装消息处理函数
  42. qInstallMessageHandler(LogOutput::customMessageHandler);// 此句执行后,qDebug,qInfo等才会输出到文件
  43. qInfo() << "-------------------日志输出模块创建成功-------------------";
  44. //deleteLog(); //删除过期日志
  45. }
  46. //卸载日志函数
  47. void LogOutput::uninstall()
  48. {
  49. qInstallMessageHandler(nullptr);
  50. }
  51. //日志信息处理函数
  52. void LogOutput::outPutMsg(QtMsgType msgType, const QMessageLogContext &context, const QString &msg)
  53. {
  54. //判断信息类型
  55. QString type;
  56. switch (msgType)
  57. {
  58. case QtDebugMsg:
  59. type = QString("Debug");
  60. break;
  61. case QtWarningMsg:
  62. type = QString("Warning");
  63. break;
  64. case QtCriticalMsg:
  65. type = QString("Critical");
  66. break;
  67. case QtFatalMsg:
  68. type = QString("Fatal");
  69. break;
  70. case QtInfoMsg:
  71. type = QString("Info");
  72. }
  73. m_mutex.lock(); //互斥关锁
  74. //文件名和行数以及函数
  75. QString contextInfo = QString("[File:(%1), Line:(%2), Funtion(%3)]:").arg(context.file).arg(context.line).arg(context.function);
  76. //获取当前时间,精确到秒
  77. QDateTime curdatetime = QDateTime::currentDateTime();
  78. QString currentDate = curdatetime.date().toString("yyyy-MM-dd");
  79. QString currentTime = curdatetime.time().toString("hh:mm:ss");
  80. if(m_curLogFile.isOpen())
  81. {
  82. bool bFileSizeLarge = (m_curLogFile.size() >= LOG_MAXSIZE) ? true : false;
  83. bool bNextDate = (currentDate.compare(m_curLogFileDate,Qt::CaseInsensitive) == 0) ? false : true;
  84. // 当系统时间过了今天的24点到达另一天,或者超过单个日志文件最大值,切换日志输出文件
  85. if(bFileSizeLarge || bNextDate)
  86. {
  87. m_curLogFile.close();
  88. // 重新打开日志输出文件(不存在则创建并打开)
  89. openTheLogFile();
  90. }
  91. }
  92. //拼接信息字符串
  93. QString message = QString("[%1 %2] %3: %4 %5").arg(currentDate).arg(currentTime).arg(type).arg(contextInfo).arg(msg);
  94. //存入信息到日志文件
  95. saveLog(message);
  96. m_mutex.unlock(); //开锁
  97. }
  98. //删除过期日志
  99. void LogOutput::deleteLog()
  100. {
  101. //获取日志文件夹地址
  102. QString dirName = logPath;
  103. QDir dir(dirName);
  104. //获取文件夹下所有文件信息列表
  105. QFileInfoList infoList = dir.entryInfoList(QDir::Files);
  106. //遍历日志文件
  107. foreach (QFileInfo fileInfo, infoList) {
  108. //将文件创建时间与过期时间作比较,如果创建时间小于过期时间,则删除(代码是一天期限,如果改月为单位可以使用addMonths)
  109. if(fileInfo.birthTime() <= QDateTime::currentDateTime().addDays(-1))
  110. {
  111. QFile::setPermissions(dirName + "/" +fileInfo.fileName(), QFileDevice::ReadOther | QFileDevice::WriteOther);
  112. if(QFile::remove(dirName + "/" +fileInfo.fileName()))
  113. {
  114. qDebug() << "过期日志文件删除成功!-->" << fileInfo.fileName();
  115. }
  116. else
  117. {
  118. qDebug() << "过期日志文件删除成功!-->" << fileInfo.fileName();
  119. }
  120. }
  121. }
  122. }
  123. //保存日志到文件
  124. void LogOutput::saveLog(QString message)
  125. {
  126. if(m_curLogFile.isOpen())
  127. {
  128. QTextStream write(&m_curLogFile);
  129. write << message << "\r\n";
  130. m_curLogFile.flush();// 刷新写入缓存
  131. }
  132. }
  133. void LogOutput::openTheLogFile()
  134. {
  135. int i = 1; //当文件大小超过最大值时,给新文件添加编号
  136. m_curLogFileDate = QDateTime::currentDateTime().toString("yyyy-MM-dd");
  137. //以天为单位给文件命名
  138. QString fileName = logPath + m_curLogFileDate + "_log";
  139. //文件名右边(后缀)
  140. QString fileNameRight;
  141. //最终要写入的文件名
  142. QString fileNameLast = fileName + ".txt";
  143. //绑定文件对象
  144. m_curLogFile.setFileName(fileNameLast);
  145. //判断文件大小
  146. while(m_curLogFile.size() >= LOG_MAXSIZE)
  147. {
  148. //给新文件加入序号后缀
  149. fileNameRight = QString("_%1.txt").arg(i);
  150. //拼接最终文件名
  151. fileNameLast = fileName + fileNameRight;
  152. //修改file绑定的文件名
  153. m_curLogFile.setFileName(fileNameLast);
  154. i++;
  155. }
  156. //只写和拼接的方式打开文件
  157. bool isopen = m_curLogFile.open(QIODevice::WriteOnly | QIODevice::Append);
  158. if(isopen == true)
  159. {
  160. }
  161. }
  162. LogOutput *LogOutput::getInstance()
  163. {
  164. QMutexLocker locker(&m_mutex); //必须加锁
  165. if(!ins){
  166. ins = new LogOutput();
  167. }
  168. return ins;
  169. }
  170. void LogOutput::customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
  171. {
  172. LogOutput::getInstance()->outPutMsg(type, context, msg); // 调用非静态成员函数处理消息
  173. };