网站建设关键词排名优化,芜湖网站建设推广公司,ui设计师简历,网站后台不显示验证码简单实现日志保存, 支持设置日志文件数量, 单个日志文件大小上限, 自动超时保存日志, 日志缓存超限保存 CLogUtils.h
#pragma once#include string
#include windows.h
#include vector
#include map
#include mutex
#include tc…简单实现日志保存, 支持设置日志文件数量, 单个日志文件大小上限, 自动超时保存日志, 日志缓存超限保存 CLogUtils.h
#pragma once#include string
#include windows.h
#include vector
#include map
#include mutex
#include tchar.h
#include thread#ifdef _UNICODE
using _tstring std::wstring;
#else
using _tstring std::string;
#endifnamespace CLogUtils
{#define USR_STRING_BUFFER_CONTENT (1) //使用字符串作为日志缓冲
#define HISTORY_FILE_MAX_COUNT (16) //最多日志文件历史数量
#define AUTO_SAVE_TIME_OUT (1000 * 60) //自动保存超时时间(毫秒)
#define LOG_FILE_MAX_SIZE (1024 * 1024 * 64) //单个日志文件大小阈值(字节)
#define LOG_BUF_MAX_COUNT (512) //日志缓冲大小阈值#define LOG_INFO(format, ...)\global_logger.Logging(_T( INFO), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LOG_DEBUG(format, ...)\global_logger.Logging(_T(DEBUG), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LOG_WARN(format, ...)\global_logger.Logging(_T( WARN), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LOG_ERROR(format, ...)\global_logger.Logging(_T(ERROR), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);class CLogHelper{public:#define LogInfo(format, ...)\Logging(_T( INFO), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LogDebug(format, ...)\Logging(_T(DEBUG), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LogWarn(format, ...)\Logging(_T( WARN), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);#define LogError(format, ...)\Logging(_T(ERROR), _T(__FILE__), _T(__FUNCTION__), __LINE__, format, ##__VA_ARGS__);public://// brief: 构造// param: nFileSize 文件大小阈值(字节)// param: nTmpCount 缓存条目阈值// param: nIntervalTime 自动存储时间间隔(毫秒)// ret: voidCLogHelper(const _tstring strDir _T(),const _tstring strName _T(),DWORD nFileSize LOG_FILE_MAX_SIZE,DWORD nTmpCount LOG_BUF_MAX_COUNT,DWORD nIntervalTime AUTO_SAVE_TIME_OUT);//删除拷贝构造与赋值重载CLogHelper(const CLogHelper) delete;CLogHelper operator (const CLogHelper) delete;~CLogHelper();//// brief: 记录一条日志// param: pstrLevel 日志等级// param: pstrFile 源码文件// param: pstrFunc 源码函数// param: nLine 行数// param: pstrFormat 格式化字符串// param: ... 可变参数// ret: voidvoid Logging(LPCTSTR pstrLevel,LPCTSTR pstrFile,LPCTSTR pstrFunc,UINT nLine,LPCTSTR pstrFormat,...);//// brief: 清空已经存储的日志文件// ret: voidvoid Clear();//// brief: 格式化字符串// param: void// ret: bool 执行结果_tstring Format(LPCTSTR pstrFormat, ...);//// brief: 获取目录下文件路径// ret: std::vector_tstring 日志文件列表std::mapint64_t, _tstring GetLogFileList(const _tstring strDir);// // brief: 获取当前进程完全路径// ret: 当前进程完全路径 如 D:\Software\HxDPortableSetup.exestatic _tstring GetCurrentModulePath();// // brief: 获取当前进程所在目录// ret: 当前进程所在目录 如 D:\Softwarestatic _tstring GetCurrentModuleDir();// // brief: 获取当前进程名// ret: 当前进程名 如 HxDPortableSetup.exestatic _tstring GetCurrentModuleName(bool bHasExt false);// // brief: 获取文件所在文件夹// param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe// ret: 文件夹 如 D:\Softwarestatic _tstring GetFileDir(const _tstring strPath);// // brief: 获取文件名// param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe// param: bHasExt 是否包含扩展名// ret: 文件夹 如 HxDPortableSetupstatic _tstring GetFileName(const _tstring strPath, bool bHasExt false);// // brief: 检查文件是否存在// param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe// ret: 是否存在 存在返回 truestatic bool IsArchive(const _tstring strPath);// // brief: 检查文件是否存在// param: strPath 文件名, 如: D:\Software\HxDPortableSetup.exe// ret: 是否存在 存在返回 truestatic bool IsDirectory(const _tstring strPath);//// brief: 创建目录(递归)// param: strPath 路径// ret: 成功返回truestatic bool CreateDir(const _tstring strPath);//// brief: 删除文件// param: strPath 路径// ret: 成功返回truestatic bool DeleteArchive(const _tstring strPath);//// brief: 获取当前时间戳字符串// param: void// ret: _tstring 时间戳字符串 如: 2023-10-11 17:43:00.617static _tstring GetCurrentTimeString();//// brief: 获取当前日期字符串// param: void// ret: _tstring 时间戳字符串 如: 2023-10-11static _tstring GetCurrentDateString();//// brief: 获取当前时间戳// param: void// ret: 时间戳(单位: 毫秒) 如: 1697017380617static int64_t GetCurrentTimestamp();//// brief: 时间戳转字符串 // param: strFormat 格式化字符串 如: %04d-%02d-%02d %02d:%02d:%02d.%d// param: timestamp 时间戳 如: 1697017380617// ret: 时间字符串 如: 2023-10-11 17:43:00.617static _tstring TimestampToString(const _tstring strFormat _T(%04d-%02d-%02d %02d:%02d:%02d.%d), int64_t timestamp 0);//// brief: 获取文件大小// param: strPath 路径// ret: 文件大小unsigned long long GetFileSize(const _tstring strPath);private://// brief: 调整日志文件数量// param: void// ret: voidvoid AdjustLogFile();//// brief: 初始化// param: void// ret: bool 执行结果bool Initialize();//// brief: 取消初始化// param: void// ret: voidvoid Uninitialize();//// brief: 初始化日志文件// param: void// ret: int 日志文件索引void InitLogFile();//// brief: 生成日志转储文件路径// param: void// ret: voidvoid GenerateLogFilePath();//// brief: 输出日志到文件// ret: bool 执行结果bool OutputToFile();private:LPTSTR m_lpBuf nullptr; //格式化字符串使用的缓冲指针std::mutex m_Lock; //线程安全锁std::vector_tstring m_logList; //日志记录std::mapint64_t, _tstring m_logFileList; //日志文件记录, 按照时间戳排序std::thread m_threadAutoSave; //自动保存线程对象HANDLE m_hEvent nullptr; //通知事件, 使用自动转储的超时等待HANDLE m_hFile INVALID_HANDLE_VALUE; //文件句柄, 日志文件写入使用int64_t m_nFileTimetamp 0; //日志文件时间戳_tstring m_strSaveDir; //日志存放目录_tstring m_strSaveName; //日志文件名_tstring m_strFilePath; //当前日志文件路径bool m_bStop false; //停止标记bool m_bFirst false; //首次记录日志标记_tstring m_strLogContent; //日志内容DWORD m_MaxFileSize 0; //文件大小阈值(到达阈值则转储到文件)DWORD m_MaxTempCount 0; //缓存条目阈值(到达阈值则转储到文件)DWORD m_AutoSaveTime 0; //自动保存间隔时间阈值(到达阈值则转储到文件)DWORD m_LogTotalSize 0; //日志文件统计DWORD m_NextItemSize 0; //下一条目日志大小DWORD m_LogItemCount 0; //日志缓冲统计};extern CLogHelper global_logger; //全局静态实例
}
CLogUtils.cpp
#include CLogUtils.h
#include strsafe.h
#include tchar.hnamespace CLogUtils
{#define FORMAT_BUFFER_CH_SIZE (1024 * 4) //字符串格式化字符缓冲大小(字符)//全局实例构造CLogHelper global_logger(_T(), CLogHelper::GetCurrentModuleName(true) _T(_global), LOG_FILE_MAX_SIZE, LOG_BUF_MAX_COUNT, AUTO_SAVE_TIME_OUT);CLogHelper::CLogHelper(const _tstring strDir/* _T()*/,const _tstring strName/* _T()*/,DWORD nFileSize/* 1024 * 1024*/,DWORD nTmpCount/* 100*/,DWORD nIntervalTime/* 60*/) : m_strSaveDir(strDir),m_strSaveName(strName),m_MaxFileSize(nFileSize), m_MaxTempCount(nTmpCount), m_AutoSaveTime(nIntervalTime){if (m_MaxFileSize LOG_FILE_MAX_SIZE){m_MaxFileSize LOG_FILE_MAX_SIZE;}if (m_AutoSaveTime AUTO_SAVE_TIME_OUT){m_AutoSaveTime AUTO_SAVE_TIME_OUT;}//默认目录为当前进程目录if (m_strSaveDir.empty()){m_strSaveDir GetCurrentModuleDir();}//默认文件名为当前进程名if (m_strSaveName.empty()){m_strSaveName GetCurrentModuleName(true);}//目录不存在就创建目录if (!IsDirectory(m_strSaveDir)){CreateDir(m_strSaveDir);}this-Initialize();}CLogHelper::~CLogHelper(){this-Uninitialize();}bool CLogHelper::Initialize(){if (nullptr m_lpBuf){m_lpBuf (LPTSTR)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, FORMAT_BUFFER_CH_SIZE * sizeof(TCHAR));}if (nullptr m_hEvent){m_hEvent ::CreateEvent(nullptr, false, false, nullptr);}//开启一个线程进行自动保存m_threadAutoSave std::move(std::thread([this](){//超时或者退出时转储日志到文件while (!m_bStop){DWORD dwWait ::WaitForSingleObject(m_hEvent, m_AutoSaveTime);switch (dwWait){case WAIT_TIMEOUT:case WAIT_OBJECT_0:{std::lock_guardstd::mutex lock(m_Lock);this-OutputToFile();m_logList.clear();}break;default:break;}}}));return nullptr ! m_lpBuf;}void CLogHelper::Uninitialize(){if (nullptr ! m_lpBuf){::HeapFree(::GetProcessHeap(), 0, m_lpBuf);m_lpBuf nullptr;}if (nullptr ! m_hEvent){m_bStop true;::SetEvent(m_hEvent);}if (m_threadAutoSave.joinable()){m_threadAutoSave.join();}if (INVALID_HANDLE_VALUE ! m_hFile){::CloseHandle(m_hFile);m_hFile INVALID_HANDLE_VALUE;}}bool CLogHelper::OutputToFile(){DWORD dwNumberOfBytesWrite 0;bool bSuccess false;if (INVALID_HANDLE_VALUE m_hFile){return false;}#if USR_STRING_BUFFER_CONTENT//没有需要写入的日志if (m_strLogContent.empty()){return true;}bSuccess ::WriteFile(m_hFile, m_strLogContent.c_str(), (DWORD)(m_strLogContent.size() * sizeof(TCHAR)), dwNumberOfBytesWrite, NULL);m_strLogContent.clear();
#else//没有需要写入的日志if (m_logList.empty()){return true;}for (const auto item : m_logList){bSuccess ::WriteFile(m_hFile, item.c_str(), (DWORD)(item.size() * sizeof(TCHAR)), dwNumberOfBytesWrite, NULL);if (!bSuccess){break;}}#endifreturn bSuccess;}void CLogHelper::Logging(LPCTSTR pstrLevel,LPCTSTR pstrFile,LPCTSTR pstrFunc,UINT nLine,LPCTSTR pstrFormat,...){if (nullptr m_lpBuf){return;}TCHAR szBuf[MAX_PATH] { 0 };DWORD dwTid ::GetCurrentThreadId();_tstring strLogContent;//日志格式前缀 [时间] [等级] [十六进制线程ID(十进制线程ID)] [源码位置 : 行数] [函数名]::StringCchPrintf(szBuf, _countof(szBuf), _T([%s] [%s] [%0.8X(%d)] [%s : %d] [%s] ),GetCurrentTimeString().c_str(),pstrLevel,dwTid,dwTid,pstrFile,nLine,pstrFunc);strLogContent szBuf;//格式化日志内容if (nullptr ! m_lpBuf){int nSize 0;va_list args;va_start(args, pstrFormat);nSize _vsntprintf_s(m_lpBuf, FORMAT_BUFFER_CH_SIZE, _TRUNCATE, pstrFormat, args);va_end(args);}//获取单行日志内容 固定前缀内容 真实内容strLogContent m_lpBuf;strLogContent _T(\r\n);m_NextItemSize (DWORD)(strLogContent.size() * sizeof(TCHAR));std::lock_guardstd::mutex lock(m_Lock);//首次启动时, 重置大小统计if (!m_bFirst){InitLogFile();AdjustLogFile();m_LogTotalSize (DWORD)GetFileSize(m_strFilePath);m_bFirst true;}//单个日志文件大小即将达到或超过阈值则输出到文件, 启用新的文件存储if ((m_LogTotalSize m_NextItemSize) m_MaxFileSize){OutputToFile();m_logList.clear();::CloseHandle(m_hFile);m_hFile INVALID_HANDLE_VALUE;(void)GenerateLogFilePath();m_LogTotalSize (DWORD)GetFileSize(m_strFilePath);AdjustLogFile();}//已缓存条目达到阈值则输出到文件
#if USR_STRING_BUFFER_CONTENTelse if (m_LogItemCount m_MaxTempCount){OutputToFile();m_strLogContent.clear();m_LogItemCount 0;}
#elseelse if (m_logList.size() m_MaxTempCount){OutputToFile();m_logList.clear();}#endif#if USR_STRING_BUFFER_CONTENTm_strLogContent strLogContent;m_LogItemCount;
#elsem_logList.emplace_back(strLogContent);
#endif//累加统计单个日志文件大小m_LogTotalSize m_NextItemSize;return;}void CLogHelper::Clear(){std::lock_guardstd::mutex lock(m_Lock);if (INVALID_HANDLE_VALUE ! m_hFile){::CloseHandle(m_hFile);m_hFile INVALID_HANDLE_VALUE;}m_logFileList GetLogFileList(m_strSaveDir);for (const auto item: m_logFileList){DeleteArchive(item.second);}m_logFileList.clear();}void CLogHelper::AdjustLogFile(){//检查文件数量是否到达阈值, 到达的话删除前面的文件if (m_logFileList.size() HISTORY_FILE_MAX_COUNT){size_t nDeleteCount m_logFileList.size() - HISTORY_FILE_MAX_COUNT;size_t nIndex 0;//删除多出的文件for (const auto item : m_logFileList){DeleteArchive(item.second);nIndex;if (nIndex nDeleteCount){break;}}//文件名整体向前移动_tstring lastPath;for (const auto item : m_logFileList){if (lastPath.empty()){::MoveFileEx(item.second.c_str(), lastPath.c_str(), MOVEFILE_DELAY_UNTIL_REBOOT);}lastPath item.second;}//从日志文件记录列表中删除for (size_t i 0; i nDeleteCount; i){m_logFileList.erase(m_logFileList.begin());}}}void CLogHelper::InitLogFile(){//如果上次最后一个日志文件大小还能存储日志, 就沿用上次的日志文件m_logFileList GetLogFileList(m_strSaveDir);if (!m_logFileList.empty()){auto itLast m_logFileList.end();itLast--;m_nFileTimetamp itLast-first;m_strFilePath itLast-second;//上次最后一个日志文件不能存储更多日志, 则生成新的日志文件路径unsigned long long ullFileSize (DWORD)GetFileSize(m_strFilePath);if ((ullFileSize m_NextItemSize) m_MaxFileSize){(void)GenerateLogFilePath();}else{//打开文件以续写日志m_hFile CreateFile(m_strFilePath.c_str(),GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);//在文件末尾追加内容LARGE_INTEGER liDistanceToMove { 0 };::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, FILE_END);}}else{(void)GenerateLogFilePath();}}void CLogHelper::GenerateLogFilePath(){//得到日志文件时间戳m_nFileTimetamp GetCurrentTimestamp();//得到日志文件路径m_strFilePath Format(_T(%s\\%s_%s.log),m_strSaveDir.c_str(),m_strSaveName.c_str(),TimestampToString(_T(%04d-%02d-%02d_%02d-%02d-%02d-%03d),m_nFileTimetamp).c_str());//创建一下文件(防止在资源管理器中看不到新的日志文件)m_hFile CreateFile(m_strFilePath.c_str(),GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);//在文件末尾追加内容LARGE_INTEGER liDistanceToMove { 0 };::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, FILE_END);m_logFileList.insert(std::make_pair(m_nFileTimetamp, m_strFilePath));}std::mapint64_t, _tstring CLogHelper::GetLogFileList(const _tstring strDir){std::mapint64_t, _tstring fileList;WIN32_FIND_DATA findData { 0 };HANDLE hFindHandle INVALID_HANDLE_VALUE;hFindHandle FindFirstFile((strDir _T(\\*.*)).c_str(), findData);if (INVALID_HANDLE_VALUE hFindHandle){return fileList;}do{_tstring strName findData.cFileName;//非目录if (!(findData.dwFileAttributes FILE_ATTRIBUTE_DIRECTORY)){//检查输入规则int nConverted 0;SYSTEMTIME st { 0 };_tstring strPath strDir _T(\\) strName;_tstring strPrefix Format(_T(%s_%%4hd-%%2hd-%%2hd_%%2hd-%%2hd-%%2hd-%%3hd.log), m_strSaveName.c_str());nConverted _stscanf_s(findData.cFileName, strPrefix.c_str(),st.wYear, st.wMonth, st.wDay, st.wHour,st.wMinute, st.wSecond, st.wMilliseconds);//检查文件名规则是否符合要求if (7 nConverted){FILETIME ftFile { 0 };FILETIME ftLocal { 0 };int64_t timestamp 0;::SystemTimeToFileTime(st, ftLocal);::LocalFileTimeToFileTime(ftLocal, ftFile);timestamp ((int64_t)ftFile.dwHighDateTime 32) | ftFile.dwLowDateTime;timestamp (timestamp - 116444736000000000) / 10000;fileList.insert(std::make_pair(timestamp, strPath));}}//上一级目录与当前目录跳过if (0 _tcscmp(findData.cFileName, _T(.)) || 0 _tcscmp(findData.cFileName, _T(..))){continue;}} while (::FindNextFile(hFindHandle, findData));::FindClose(hFindHandle);return fileList;}_tstring CLogHelper::Format(LPCTSTR pstrFormat, ...){_tstring strResult;if (nullptr ! m_lpBuf){int nSize 0;va_list args;va_start(args, pstrFormat);nSize _vsntprintf_s(m_lpBuf, FORMAT_BUFFER_CH_SIZE, _TRUNCATE, pstrFormat, args);va_end(args);strResult m_lpBuf;}return strResult;}_tstring CLogHelper::GetCurrentTimeString(){TCHAR szBuf[MAX_PATH] { 0 };SYSTEMTIME st { 0 };(void)::GetLocalTime(st);::StringCchPrintf(szBuf, _countof(szBuf),_T(%04d-%02d-%02d %02d:%02d:%02d.%d),st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);return szBuf;}_tstring CLogHelper::GetCurrentDateString(){TCHAR szBuf[MAX_PATH] { 0 };SYSTEMTIME st { 0 };(void)::GetLocalTime(st);::StringCchPrintf(szBuf, _countof(szBuf), _T(%04d-%02d-%02d), st.wYear, st.wMonth, st.wDay);return szBuf;}int64_t CLogHelper::GetCurrentTimestamp(){int64_t timeStamp 0;(void)::GetSystemTimeAsFileTime((FILETIME*)timeStamp);return (timeStamp - 116444736000000000) / 10000;}_tstring CLogHelper::TimestampToString(const _tstring strFormat, int64_t timestamp){TCHAR szBuf[MAX_PATH] { 0 };SYSTEMTIME st { 0 };FILETIME ftFile { 0 };FILETIME ftLocal { 0 };timestamp timestamp * 10000 116444736000000000;ftFile.dwLowDateTime timestamp 0xFFFFFFFF;ftFile.dwHighDateTime timestamp 32;::FileTimeToLocalFileTime(ftFile, ftLocal);::FileTimeToSystemTime(ftLocal, st);::StringCchPrintf(szBuf, _countof(szBuf),strFormat.c_str(),st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);return szBuf;}_tstring CLogHelper::GetCurrentModulePath(){TCHAR szCurPath[MAX_PATH] { 0 };::GetModuleFileName(NULL, szCurPath, _countof(szCurPath));_tstring strResult szCurPath;return strResult;}_tstring CLogHelper::GetCurrentModuleDir(){return GetFileDir(GetCurrentModulePath());}_tstring CLogHelper::GetCurrentModuleName(bool bHasExt/* true*/){return GetFileName(GetCurrentModulePath(), bHasExt);}_tstring CLogHelper::GetFileDir(const _tstring strPath){_tstring strResult;size_t nIndex strPath.find_last_of(_T(\\));if (nIndex ! _tstring::npos){strResult strPath.substr(0, nIndex);}return strResult;}_tstring CLogHelper::GetFileName(const _tstring strPath, bool bHasExt/* true*/){_tstring strResult strPath;size_t nIndex strResult.find_last_of(_T(\\));if (nIndex ! _tstring::npos){strResult strResult.substr(nIndex 1);}if (!bHasExt){nIndex strResult.find_last_of(_T(.));if (nIndex ! _tstring::npos){return strResult.substr(0, nIndex);}}return strResult;}bool CLogHelper::IsArchive(const _tstring strPath){WIN32_FILE_ATTRIBUTE_DATA attr { 0 };if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, attr)){return false;}return attr.dwFileAttributes FILE_ATTRIBUTE_ARCHIVE;}bool CLogHelper::IsDirectory(const _tstring strPath){WIN32_FILE_ATTRIBUTE_DATA attr { 0 };if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, attr)){return false;}return attr.dwFileAttributes FILE_ATTRIBUTE_DIRECTORY;}bool CLogHelper::CreateDir(const _tstring strPath){_tstring strDriver; //驱动器号, 如 D:_tstring strSubPath strPath; //路径, 如 Test\1\2\3if (strPath.empty()){return false;}//获取盘符do{size_t nFindIndex strPath.find_first_of(:); //检查是否有驱动器号if (nFindIndex _tstring::npos){break;}strDriver strPath.substr(0, nFindIndex 1); //得到驱动器号, 如 D:nFindIndex strPath.find(_T(\\), nFindIndex);if (nFindIndex _tstring::npos){break;}strSubPath strPath.substr(nFindIndex 1); //得到路径, 如 Test\1\2\3} while (false);_tstring strDestDir;size_t nFindBegin 0;size_t nFindIndex 0;do{nFindIndex strSubPath.find(_T(\\), nFindBegin);if (nFindIndex ! _tstring::npos){strDestDir strSubPath.substr(0, nFindIndex);nFindBegin nFindIndex 1;}else{strDestDir strSubPath;}if (!strDriver.empty()){strDestDir strDriver _T(\\) strDestDir;}if (!::CreateDirectory(strDestDir.c_str(), NULL) ERROR_ALREADY_EXISTS ! ::GetLastError()){return false;}} while (nFindIndex ! _tstring::npos);return true;}bool CLogHelper::DeleteArchive(const _tstring strPath){if (strPath.empty()){return false;}return ::DeleteFile(strPath.c_str());}unsigned long long CLogHelper::GetFileSize(const _tstring strPath){unsigned long long ullSize 0;WIN32_FILE_ATTRIBUTE_DATA attr { 0 };if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, attr)){return 0;}ullSize (unsigned long long)attr.nFileSizeHigh 32 | attr.nFileSizeLow;return ullSize;}}使用
main.cpp
#include iostream
#include CLogUtils.h
#include tchar.hint _tmain(int argc, LPCTSTR argv[])
{while (true){uint64_t uBegin CLogUtils::CLogHelper::GetCurrentTimestamp();uint64_t uEnd 0;int nCount 10000;std::cout CurrentTimestamp: uBegin std::endl;for (int i 0; i nCount; i){CLogUtils::LOG_INFO(_T(%d %s), 1024, _T(FlameCyclone));}uEnd CLogUtils::CLogHelper::GetCurrentTimestamp();std::cout Repeat nCount Cost time: uEnd - uBegin std::endl;system(pause);}return 0;
}x64 Debug效果: x64 Release效果: