C++写日志源代码分析,可实现根据日期自动创建文件夹、日志分类、文件大小控制等

            最近在做一个项目,使用C++写一个动态链接库(dll),里面需要有日志功能,于是参考网上的资料实现了C++写日志的功能。日志可以指定路径保存,也可以默认保存在当前可执行程序(exe)所在的文件夹。现在把源代码贴出来与大家共享,还请各位大神批评指正。

    头文件:writeLog.h


   
   
  1. /************************************************************************/
  2. #ifndef _WRITELOG_H
  3. #define _WRITELOG_H
  4. #include <time.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stdarg.h>
  8. #include <Windows.h>
  9. #include <memory.h>
  10. #define LOG_WRITE_STATE 1 /*写日志条件,1:写日志,0:不写日志*/
  11. #define LOG_SUCCESS 0 /*写日志成功标志*/
  12. #define LOG_FAILED (-1) /*写日志失败标志*/
  13. #define DWORD_NULL (0xFFFFFFFF)
  14. #define MAX_LINE_LEN 1024 /*每行日志的最大长度*/
  15. #define MAX_FILE_PATH 256 /*日志文件路径的最大长度*/
  16. #define MAX_LOG_FILE_SIZE (512*1024) /*日志文件内容的最大长度*/
  17. #define MAX_LOG_NAME_LEN 256 /*日志文件名的最大长度*/
  18. #define LOG_TYPE_INFO 0 /*日志类型:错误类型*/
  19. #define LOG_TYPE_SYSTEM 1 /*日志类型:系统类型*/
  20. #define LOG_TYPE_ERROR 2 /*日志类型:错误类型*/
  21. /*日志内容结构体*/
  22. struct logData
  23. {
  24. char strDate[ 11]; /*日期:格式为2014-07-01*/
  25. char strTime[ 9]; /*时间,格式为20:12:06*/
  26. unsigned char logType; /*日志类型:INFO(0),SYSTEM(1),ERROR(2)*/
  27. char logText[MAX_LINE_LEN]; /*每行的日志内容*/
  28. };
  29. #endif
    源文件:writeLog.cpp


   
   
  1. /************************************************************************/
  2. #include "writeLog.h"
  3. #include <io.h>
  4. #include <direct.h>
  5. int writeLogText(logData *pLogData); /*写日志内容*/
  6. void writeLog(unsigned char type, char *pStrText); /*写日志*/
  7. int createLogDir(char *pStrPath); /*创建保存日志的路径*/
  8. int createLogFile(const char *pStrPath, int iPos); /*创建保存日志的文件夹*/
  9. bool IsFileExist(const char *pStrFile); /*判断文件是否存在*/
  10. int getLogPath(char *pStrPath); /*获取日志的路径*/
  11. DWORD getFileLen(const char *pFile); /*获取文件长度*/
  12. int getLogFileName(int logType, const char *pStrPath, char *pStrName); /*获取日志文件名*/
  13. /************************************************************************/
  14. /*
  15. 函数名称:int writeLogText(logData *pLogData)
  16. 说明:写日志内容
  17. 参数:pLogData是指向logData结构体的指针
  18. 返回值:LOG_SUCCESS(0)表示成功,LOG_FAILED(-1)表示失败
  19. */
  20. /************************************************************************/
  21. int writeLogText(logData *pLogData)
  22. {
  23. char filePath[MAX_FILE_PATH];
  24. char fileName[MAX_LOG_NAME_LEN];
  25. FILE *pFile = NULL;
  26. char logText[MAX_LINE_LEN];
  27. memset(filePath, 0, MAX_FILE_PATH);
  28. memset(fileName, 0, MAX_LOG_NAME_LEN);
  29. memset(logText, 0, MAX_LINE_LEN);
  30. getLogPath(filePath);
  31. getLogFileName(pLogData->logType, filePath, fileName);
  32. //pFile = fopen(fileName, "a+");
  33. int r = fopen_s(&pFile, fileName, "a+");
  34. if( NULL == pFile)
  35. return LOG_FAILED;
  36. sprintf_s(logText, sizeof(logText), "%s %s %s\n", pLogData->strDate, pLogData->strTime, pLogData->logText);
  37. fwrite(logText, 1, strlen(logText), pFile);
  38. fclose(pFile);
  39. return LOG_SUCCESS;
  40. }
  41. /************************************************************************/
  42. /*
  43. 函数名称:void writeLog(unsigned char type, char *pStrText)
  44. 说明:写日志函数
  45. 参数:type:日志类型,pStrText:指向日志内容的指针
  46. 返回值:无
  47. */
  48. /************************************************************************/
  49. void writeLog(unsigned char type, char *pStrText)
  50. {
  51. logData data;
  52. time_t currTime;
  53. struct tm *mt;
  54. memset(&data, 0, sizeof(logData));
  55. data.logType = type;
  56. strcpy(data.logText, pStrText);
  57. currTime = time( NULL);
  58. mt = localtime(&currTime);
  59. strftime(data.strDate, sizeof(data.strDate), "%Y-%m-%d", mt);
  60. strftime(data.strTime, sizeof(data.strTime), "%H:%M:%S", mt);
  61. writeLogText(&data);
  62. }
  63. /************************************************************************/
  64. /*
  65. 函数名:int createLogDir(char *pStrPath)
  66. 参数:pStrPath是用户指定的根路径
  67. 说明:创建日志存放路径
  68. 返回值:LOG_SUCCESS:成功
  69. LOG_FAILED:失败
  70. */
  71. /************************************************************************/
  72. int createLogDir(char *pStrPath)
  73. {
  74. char *tag = NULL;
  75. for (tag = pStrPath;*tag != NULL;tag++)
  76. {
  77. if ( '\\' == *tag)
  78. {
  79. char path[MAX_FILE_PATH];
  80. char buff[MAX_FILE_PATH];
  81. strcpy(buff, pStrPath);
  82. buff[ strlen(pStrPath) - strlen(tag) + 1] = NULL;
  83. strcpy(path, buff);
  84. if (_access(path, 0) == -1)
  85. {
  86. int r = _mkdir(path);
  87. if ( -1 == r)
  88. {
  89. return LOG_FAILED;
  90. }
  91. }
  92. }
  93. }
  94. return LOG_SUCCESS;
  95. }
  96. /************************************************************************/
  97. /*
  98. 函数名:int createLogFile(const char *pStrPath, int iPos)
  99. 参数:pStrPath:文件名,iPos:文件指针位置
  100. 说明:创建日志文件
  101. 返回值:LOG_SUCCESS:成功
  102. LOG_FAILED:失败
  103. */
  104. /************************************************************************/
  105. int createLogFile(const char *pStrPath, int iPos)
  106. {
  107. HANDLE hd = 0;
  108. int iRet = 0;
  109. if ( NULL == pStrPath)
  110. {
  111. return LOG_FAILED;
  112. }
  113. hd = CreateFile(pStrPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  114. if (INVALID_HANDLE_VALUE == hd)
  115. {
  116. return LOG_FAILED;
  117. }
  118. if (DWORD_NULL == SetFilePointer(hd, iPos, NULL, FILE_BEGIN))
  119. {
  120. return LOG_FAILED;
  121. }
  122. iRet = SetEndOfFile(hd);
  123. CloseHandle(hd);
  124. return iRet;
  125. }
  126. /************************************************************************/
  127. /*
  128. 函数名:bool IsFileExist(const char *pStrFile)
  129. 参数:pStrFile,文件名
  130. 说明:判断指定的文件是否存在
  131. 返回值:true:存在
  132. false:不存在
  133. */
  134. /************************************************************************/
  135. bool IsFileExist(const char *pStrFile)
  136. {
  137. int iLen = 0;
  138. WIN32_FIND_DATA findData;
  139. memset(&findData, 0, sizeof(WIN32_FIND_DATA));
  140. HANDLE hd = FindFirstFile(pStrFile, &findData);
  141. if (INVALID_HANDLE_VALUE == hd)
  142. {
  143. DWORD dwRet = GetLastError();
  144. if (ERROR_FILE_NOT_FOUND == dwRet || ERROR_PATH_NOT_FOUND == dwRet)
  145. {
  146. return false;
  147. }
  148. }
  149. FindClose(hd);
  150. return true;
  151. }
  152. /************************************************************************/
  153. /*
  154. 函数名:int getLogPath(char *pStrPath)
  155. 参数:pStrPath,文件名
  156. 说明:获取日志文件路径
  157. 返回值:LOG_SUCCESS:成功
  158. LOG_FAILED:失败
  159. */
  160. /************************************************************************/
  161. int getLogPath(char *pStrPath)
  162. {
  163. if ( NULL == pStrPath)
  164. {
  165. return LOG_FAILED;
  166. }
  167. char currDir[MAX_FILE_PATH]; // = "F:\\writelog";
  168. memset(currDir, 0, MAX_FILE_PATH);
  169. int iRet = 0;
  170. time_t currTime = time( NULL);
  171. struct tm *mt = localtime(&currTime);
  172. /*根据日期组成文件夹名*/
  173. GetModuleFileName( NULL, currDir, MAX_FILE_PATH);
  174. //(strrchr(currDir, '\\'))[1] = 0;
  175. int temp = 0;
  176. for ( int i = sizeof(currDir);i > 0;i--)
  177. {
  178. if (currDir[i] == '\\')
  179. {
  180. temp = i;
  181. break;
  182. }
  183. }
  184. currDir[temp + 1] = 0;
  185. sprintf(pStrPath, "%s%d%02d%02d\\", currDir, mt->tm_year + 1900, mt->tm_mon + 1, mt->tm_mday);
  186. iRet = createLogDir(pStrPath);
  187. return iRet;
  188. }
  189. /*********************************************************************
  190. * 函数名称:DWORD getFileLen(const char *pFile)
  191. * 说明:获取指定的文件大小
  192. * 输入参数:
  193. * const char *pFile --文件名
  194. * 返回值:
  195. * DWORD -- 文件大小
  196. *********************************************************************/
  197. DWORD getFileLen(const char *pFile)
  198. {
  199. WIN32_FIND_DATA data;
  200. HANDLE hd = NULL;
  201. memset(&data, 0, sizeof(WIN32_FIND_DATA));
  202. hd = FindFirstFile(pFile, &data);
  203. FindClose(hd);
  204. return (data.nFileSizeHigh * MAXDWORD) + data.nFileSizeLow;
  205. }
  206. /*********************************************************************
  207. * 函数名称:int getLogFileName(int logType, const char *pStrPath, char *pStrName);
  208. * 说明:获取日志文件名
  209. * 输入参数:
  210. * int logType -- 日志类型 3种:INFO(0)/ERROR(1)/SYSTEM(2)
  211. * const char *pStrPath -- 日志路径 由getLogPath得到
  212. * 输出参数:
  213. * char *pStrName -- 日志文件名
  214. * 返回值:
  215. * int -- LOG_FAILED: 失败
  216. * -- LOG_SUCCESS: 成功
  217. *********************************************************************/
  218. int getLogFileName(int logType, const char *pStrPath, char *pStrName)
  219. {
  220. if ( NULL == pStrPath)
  221. {
  222. return LOG_FAILED;
  223. }
  224. char logName[MAX_FILE_PATH];
  225. FILE *pFile = NULL;
  226. memset(logName, 0, MAX_FILE_PATH);
  227. switch(logType)
  228. {
  229. case LOG_TYPE_INFO:
  230. sprintf_s(logName, sizeof(logName), "%s\\dll_log_info", pStrPath);
  231. break;
  232. case LOG_TYPE_ERROR:
  233. sprintf_s(logName, sizeof(logName), "%s\\dll_log_error", pStrPath);
  234. break;
  235. case LOG_TYPE_SYSTEM:
  236. sprintf_s(logName, sizeof(logName), "%s\\dll_log_system", pStrPath);
  237. break;
  238. default:
  239. return LOG_FAILED;
  240. break;
  241. }
  242. strcat(logName, ".txt");
  243. if (IsFileExist(logName))
  244. {
  245. /*如果文件长度大于指定的最大长度,则重新创建一个文件覆盖原文件*/
  246. if (( int)getFileLen(logName) + 256 >= MAX_LOG_FILE_SIZE)
  247. {
  248. createLogFile(logName, 0);
  249. }
  250. }
  251. else
  252. createLogFile(logName, 0);
  253. sprintf(pStrName, "%s", logName);
  254. return LOG_SUCCESS;
  255. }
  256. //测试代码
  257. int main()
  258. {
  259. writeLog(LOG_TYPE_SYSTEM, "program begin.");
  260. return 0;
  261. }



            </div>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值