// // Log.h // // 说明:模拟 IOSTREAM 的多功能简易写LOG代码 // 可用于_Debug和_Release, _WIN32和_MFC // // LOG_DEBUG:只在_DEBUG下起作用 // LOG_RELEASE: 只在Release下起作用 // LOG_OUTPUT: 在输出窗口打印LOG信息 // LOG_CONSOLE: 在console窗口打印LOG信息,MFC下不输出 // LOG_FILE: 输出LOG文件,默认路径Log.txt,可以用OpenLog设置路径 // // 可以按自己需要组合上述标志,在构造函数中设置,比如 CLog log(CLog::LOG_DEBUG|CLog::LOG_FILE); // // 联系: gch_zsu@163.com // 作者: GaoChuan // // 欢迎指导! // 版权所有,未经允许,请勿转载!哈哈! // // #ifndef __LOG__H__GAO__GCH_ZSU_163_COM_ #define __LOG__H__GAO__GCH_ZSU_163_COM_ #define __EMAIL__ gch_zsu@163.com #define __WEBSITE__ http://hi.csdn.net/NewbieCoder #include <stdio.h> #include <tchar.h> #include <assert.h> #pragma warning(disable:4313) #pragma warning(disable:4305) #pragma warning(disable:4244) const unsigned BUF_SIZE = 1024; class CStreamBuf { public: enum FMT_FLAG{ FMT_NONE = 0x0, //0 FMT_HEX = 0x10,//十六进制输出标记 FMT_OCT = 0x8 //八进制输出标记 }; public: CStreamBuf(unsigned uLen = BUF_SIZE); virtual ~CStreamBuf(); TCHAR *GetString(); unsigned GetStringCount(); void Reset(); void SetFmt(FMT_FLAG fmt);//0,8,16 bool Int64Fmt(TCHAR *_buf, int _fmt, unsigned __int64 _in64); public: CStreamBuf& operator <<(bool param); CStreamBuf& operator <<(short param); CStreamBuf& operator <<(unsigned short param); CStreamBuf& operator <<(int param); CStreamBuf& operator <<(unsigned param); CStreamBuf& operator <<(long param); CStreamBuf& operator <<(unsigned long param); CStreamBuf& operator <<(__int64 param); CStreamBuf& operator <<(unsigned __int64 param); CStreamBuf& operator <<(float param); CStreamBuf& operator <<(double param); CStreamBuf& operator <<(long double param); CStreamBuf& operator <<(const void* param); CStreamBuf& operator <<(char param); CStreamBuf& operator <<(wchar_t param); CStreamBuf& operator <<(TCHAR* param); protected: TCHAR *m_pBuf; TCHAR *m_pWrite; unsigned m_uCount; unsigned m_uLeft; FMT_FLAG m_fmt_flag; }; class CLog { public: enum{ LOG_NONE = 0x0,//不输出 LOG_FILE = 0x1,//文件输出 LOG_OUTPUT = 0x2,//输出窗口输出 LOG_CONSOLE = 0x4,//console窗口输出 LOG_DEBUG = 0x8,//_Debug时输出 LOG_RELEASE = 0x10//_Release时输出 }; public: CLog(unsigned flag = (LOG_DEBUG|LOG_OUTPUT)); virtual ~CLog(); inline bool IsFmtMath(); public: CLog& operator <<(bool param); CLog& operator <<(short param); CLog& operator <<(unsigned short param); CLog& operator <<(int param); CLog& operator <<(unsigned param); CLog& operator <<(long param); CLog& operator <<(unsigned long param); CLog& operator <<(__int64 param); CLog& operator <<(unsigned __int64 param); CLog& operator <<(float param); CLog& operator <<(double param); CLog& operator <<(long double param); CLog& operator <<(const void* param); CLog& operator <<(char param); CLog& operator <<(wchar_t param); CLog& operator <<(char* param); CLog& operator <<(wchar_t* param); CLog& operator <<(CLog& (*fun)(CLog& log)); inline CLog& hex(CLog& log); inline CLog& oct(CLog& log); bool OpenLog(const TCHAR *path); CLog& flush(CLog& log); CLog& endl(CLog& log); inline CStreamBuf *GetStream(){ return m_pBuf; } protected: CStreamBuf *m_pBuf; unsigned m_flag; TCHAR *m_path; FILE *m_pFile; }; //十六进制输出 extern inline CLog& hex(CLog& log); //八进制输出 extern inline CLog& oct(CLog& log); //输出缓冲区内容 extern inline CLog& flush(CLog& log); //输出缓冲区内容并换行 extern inline CLog& endl(CLog& log); #endif #include "Log.h" #include <windows.h> #include <atltrace.h> CStreamBuf::CStreamBuf(unsigned uLen /* = 1024 */) :m_pBuf(NULL) { m_pBuf = new TCHAR[uLen]; memset(m_pBuf,0,uLen); m_pWrite = m_pBuf; m_uCount = uLen - 1; m_uLeft = uLen - 1; m_fmt_flag = FMT_NONE; } CStreamBuf::~CStreamBuf() { m_uLeft = 0; m_uCount = 0; m_fmt_flag = FMT_NONE; if (m_pBuf != NULL) { delete []m_pBuf; m_pBuf = NULL; } } TCHAR* CStreamBuf::GetString() { return m_pBuf; } unsigned CStreamBuf::GetStringCount() { return (m_uCount - m_uLeft); } void CStreamBuf::Reset() { m_pBuf[0] = _T('/0'); m_pWrite = m_pBuf; m_uLeft = m_uCount; } void CStreamBuf::SetFmt(FMT_FLAG fmt) { m_fmt_flag = fmt; } bool CStreamBuf::Int64Fmt(TCHAR *_buf, int _fmt, unsigned __int64 _in64) { int size = 0; TCHAR buf[30]; unsigned __int64 in64 = _in64; unsigned __int64 tmp = 0; unsigned __int64 _tmp = _in64; while (in64) { if((tmp = in64 % _fmt) >= 10) { buf[size] = (tmp - 10) + 'A'; } else { buf[size] = tmp + '0'; } in64 = in64/_fmt; size++; } int i; for (i=0,size--; size>=0; size--) { _buf[i] = buf[size]; i++; } _buf[i] = _T('/0'); return true; } CStreamBuf& CStreamBuf::operator <<(bool param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(short param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(unsigned short param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(int param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(unsigned param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(long param) { (*this)<<((__int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(unsigned long param) { (*this)<<((unsigned __int64)param); return (*this); } CStreamBuf& CStreamBuf::operator <<(__int64 param) { TCHAR _buf[30]; if (m_fmt_flag == FMT_NONE) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%lld"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%lld"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } else if (m_fmt_flag&FMT_HEX) { Int64Fmt(_buf,FMT_HEX,param); } else if (m_fmt_flag&FMT_OCT) { Int64Fmt(_buf,FMT_OCT,param); } (*this)<<_buf; return (*this); } CStreamBuf& CStreamBuf::operator <<(unsigned __int64 param) { TCHAR _buf[30]; if (m_fmt_flag == FMT_NONE) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%llu"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%llu"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } else if (m_fmt_flag&FMT_HEX) { Int64Fmt(_buf,FMT_HEX,param); } else if (m_fmt_flag&FMT_OCT) { Int64Fmt(_buf,FMT_OCT,param); } (*this)<<_buf; return (*this); } CStreamBuf& CStreamBuf::operator <<(float param) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%.5f"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%.5f"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } CStreamBuf& CStreamBuf::operator <<(double param) { (*this)<<(float)param; return (*this); } CStreamBuf& CStreamBuf::operator <<(long double param) { (*this)<<(float)param; return (*this); } CStreamBuf& CStreamBuf::operator <<(const void* param) { int _size = 0; TCHAR str[10]; #ifdef _UNICODE _size = _snwprintf_s(str,10,8,_T("%X"),param); #else _size = _snprintf_s(str,10,8,_T("%X"),param); #endif for (int i=0; i<8 -_size; i++) { (*this)<<(int)0; } #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,10,8,_T("%X"),param); #else _size = _snprintf_s(m_pWrite,10,8,_T("%X"),param); #endif m_pWrite += 8; *m_pWrite = '/0'; m_uLeft -= 8; return (*this); } CStreamBuf& CStreamBuf::operator <<(char param) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%c"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%c"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } CStreamBuf& CStreamBuf::operator <<(wchar_t param) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%c"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%c"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } CStreamBuf& CStreamBuf::operator <<(TCHAR *param) { int _size = 0; #ifdef _UNICODE _size = _snwprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%s"),param); #else _size = _snprintf_s(m_pWrite,m_uLeft,m_uLeft,_T("%s"),param); #endif m_pWrite += _size; *m_pWrite = '/0'; m_uLeft -= _size; return (*this); } CLog::CLog(unsigned flag /* = (LOG_DEBUG|LOG_OUTPUT) */ ) :m_pBuf(new CStreamBuf) ,m_flag(flag) ,m_pFile(NULL) ,m_path(NULL) { //Write Log Msg Into Log File if (m_flag&LOG_FILE) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { TCHAR *path = _T("Log.txt"); if((m_path = new TCHAR[261]) != NULL) { OpenLog(path); } } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { TCHAR *path = _T("Log.txt"); if((m_path = new TCHAR[261]) != NULL) { OpenLog(path); } } #endif //_DEBUG } } CLog::~CLog() { if (m_path != NULL) { delete []m_path; m_path = NULL; } if (m_pFile != NULL) { fclose(m_pFile); } if (m_pBuf != NULL) { delete m_pBuf; m_pBuf = NULL; } } bool CLog::IsFmtMath() { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { if (m_flag&LOG_FILE || m_flag&LOG_OUTPUT || m_flag&LOG_CONSOLE) { return true; } } #else //RELEASE if (m_flag&LOG_RELEASE) { if (m_flag&LOG_FILE || m_flag&LOG_OUTPUT || m_flag&LOG_CONSOLE) { return true; } } #endif return false; } CLog& CLog::operator <<(bool param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(short param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(unsigned short param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(int param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(unsigned param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(long param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(unsigned long param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(__int64 param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(unsigned __int64 param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(float param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(double param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(long double param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(const void* param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(char param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(wchar_t param) { if (!IsFmtMath()) { return (*this); } (*m_pBuf)<<param; return (*this); } CLog& CLog::operator <<(char *param) { if (!IsFmtMath()) { return (*this); } #ifdef _UNICODE int _size = MultiByteToWideChar (CP_ACP, 0, param, -1, NULL, 0); TCHAR *str = new TCHAR[_size+1]; MultiByteToWideChar (CP_ACP, 0, param, -1, str, _size+1); str[_size] = '/0'; (*m_pBuf)<<str; if (str != NULL) { delete []str; str = NULL; } #else (*m_pBuf)<<param; #endif return (*this); } CLog& CLog::operator <<(wchar_t *param) { if (!IsFmtMath()) { return (*this); } #ifndef _UNICODE int _size = WideCharToMultiByte(CP_ACP, 0, param, -1, NULL, 0, NULL, NULL); TCHAR *str = new TCHAR[_size+1]; WideCharToMultiByte(CP_ACP, 0, param, -1, str, _size+1, NULL, NULL); str[_size] = '/0'; (*m_pBuf)<<str; if (str != NULL) { delete []str; str = NULL; } #else (*m_pBuf)<<param; #endif return (*this); } CLog& CLog::operator <<(CLog& (*fun)(CLog& log)) { if (!IsFmtMath()) { return (*this); } fun(*this); return (*this); } CLog& hex(CLog& log) { return log.hex(log); } CLog& oct(CLog& log) { return log.oct(log); } CLog& flush(CLog& log) { return log.flush(log); } CLog& endl(CLog& log) { return log.endl(log); } CLog& CLog::hex(CLog& log) { if (!IsFmtMath()) { return (*this); } if (m_pBuf != NULL) { m_pBuf->SetFmt(CStreamBuf::FMT_HEX); } return (log); } CLog& CLog::oct(CLog& log) { if (!IsFmtMath()) { return (*this); } if (m_pBuf != NULL) { m_pBuf->SetFmt(CStreamBuf::FMT_OCT); } return (log); } bool CLog::OpenLog(const TCHAR *path) { if (!IsFmtMath()) { return false; } assert(path != NULL); size_t size = _tcslen(path); #ifdef _UNICODE if(wmemcpy_s(m_path,260,path,size)) { m_path[0] = _T('/0'); return false; } #else if(memcpy_s(m_path,260,path,size)) { m_path[0] = _T('/0'); return false; } #endif m_path[size] = _T('/0'); if (m_pFile != NULL) { fclose(m_pFile); } assert(m_path != NULL); if (m_path[0] != _T('/0')) { errno_t err; #ifdef _UNICODE err = ::_wfopen_s(&m_pFile,m_path,_T("w")); #else err = ::fopen_s(&m_pFile,m_path,_T("w")); #endif assert(m_pFile != NULL); if (err != 0) { return false; } return true; } return false; } CLog& CLog::flush(CLog& log) { if (!IsFmtMath()) { return (*this); } int _size = log.GetStream()->GetStringCount(); if (_size == 0) { return log; } bool _flag = true; //Write Log Msg Into Output Window if (m_flag&LOG_OUTPUT) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { OutputDebugString((log.GetStream()->GetString())); } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { OutputDebugString((log.GetStream()->GetString())); } #endif //_DEBUG } //Write Log Msg Into Console Window #ifndef _CONSOLE #else if (m_flag&LOG_CONSOLE) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { #ifdef _UNICODE if(wprintf(_T("%s"),log.GetStream()->GetString()) != _size ) { _flag = false; } #else if(printf(_T("%s"),log.GetStream()->GetString()) != _size) { _flag = false; } #endif //_UNICODE } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { #ifdef _UNICODE if(wprintf(_T("%s"),log.GetStream()->GetString()) != _size ) { _flag = false; } #else if(printf(_T("%s"),log.GetStream()->GetString()) != _size) { _flag = false; } #endif //_UNICODE } #endif //_DEBUG } #endif //_CONSOLE //Write Log Msg Into Log File if (m_flag&LOG_FILE) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { #ifdef _UNICODE if(fwprintf_s(m_pFile,_T("%s"),log.GetStream()->GetString()) != _size ) { _flag = false; } #else if(fprintf_s(m_pFile,_T("%s"),log.GetStream()->GetString()) != log.GetStream()->GetStringCount()) { _flag = false; } #endif //_UNICODE } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { #ifdef _UNICODE if(fwprintf_s(m_pFile,_T("%s"),log.GetStream()->GetString()) != _size ) { _flag = false; } #else if(fprintf_s(m_pFile,_T("%s"),log.GetStream()->GetString()) != log.GetStream()->GetStringCount()) { _flag = false; } #endif //_UNICODE } #endif //_DEBUG } if (!_flag) { OutputDebugString(_T("写入Log失败!/n")); } log.GetStream()->Reset(); return (log); } CLog& CLog::endl(CLog& log) { if (!IsFmtMath()) { return (*this); } log.flush(log); //Write Log Msg Into Output Window if (m_flag&LOG_OUTPUT) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { OutputDebugString(_T("/n")); } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { OutputDebugString(_T("/n")); } #endif //_DEBUG } //Write Log Msg Into Console Window #ifndef _CONSOLE #else if (m_flag&LOG_CONSOLE) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { #ifdef _UNICODE wprintf(_T("%s"),_T("/n")); #else printf(_T("%s"),_T("/n")); #endif //_UNICODE } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { #ifdef _UNICODE wprintf(_T("%s"),_T("/n")); #else printf(_T("%s"),_T("/n")); #endif //_UNICODE } #endif //_DEBUG } #endif //_CONSOLE //Write Log Msg Into Log File if (m_flag&LOG_FILE) { #ifdef _DEBUG if (m_flag&LOG_DEBUG) { #ifdef _UNICODE fwprintf_s(m_pFile,_T("%s"),_T("/n")); #else fprintf_s(m_pFile,_T("%s"),_T("/n")); #endif //_UNICODE } #endif //_DEBUG #ifndef _DEBUG if (m_flag&LOG_RELEASE) { #ifdef _UNICODE fwprintf_s(m_pFile,_T("%s"),_T("/n")); #else fprintf_s(m_pFile,_T("%s"),_T("/n")); #endif //_UNICODE } #endif //_DEBUG } return (log); } 测试数据: #include "Log.h" int main() { CLog log; log<<"[LOG] [bool in log:] "<<true<<" [/LOG]"<<endl; log<<"[LOG] [short int in log:] "<<(short int)0xffff<<" [/LOG]"<<endl; log<<"[LOG] [unsigned int in log:] "<<(unsigned short int)0xffff<<" [/LOG]"<<endl; log<<"[LOG] [int32 in log:] "<<(int)0xffffffff<<" [/LOG]"<<endl; log<<"[LOG] [unsigned int32 in log:] "<<(unsigned int)0xffffffff<<" [/LOG]"<<endl; log<<"[LOG] [long in log:] "<<(long)88888888<<" [/LOG]"<<endl; log<<"[LOG] [unsigned long in log:] "<<(unsigned long)888888888<<" [/LOG]"<<endl; log<<"[LOG] [int64 in log:] "<<(__int64)0xfffffffffffffff<<" [/LOG]"<<endl; log<<"[LOG] [unsigned int64 in log:] "<<(unsigned __int64)0xffffffffffffffff<<" [/LOG]"<<endl; log<<"[LOG] [float in log:] "<<(float)3.14159265<<" [/LOG]"<<endl; log<<"[LOG] [hex in log:] "<<hex<<0xffffffff<<" [/LOG]"<<endl; log<<"[LOG] [oct in log:] "<<oct<<0777777777<<" [/LOG]"<<endl; log<<"[LOG] [String in log:] "<<"This is a test string."<<flush<<" This is another test string."<<" [/LOG]"<<endl; return 0; } 输出结果:(输出窗口) [LOG] [bool in log:] 1 [/LOG] [LOG] [short int in log:] -1 [/LOG] [LOG] [unsigned int in log:] 65535 [/LOG] [LOG] [int32 in log:] -1 [/LOG] [LOG] [unsigned int32 in log:] 4294967295 [/LOG] [LOG] [long in log:] 88888888 [/LOG] [LOG] [unsigned long in log:] 888888888 [/LOG] [LOG] [int64 in log:] 1152921504606846975 [/LOG] [LOG] [unsigned int64 in log:] 18446744073709551615 [/LOG] [LOG] [float in log:] 3.14159 [/LOG] [LOG] [hex in log:] FFFFFFFF [/LOG] [LOG] [oct in log:] 777777777 [/LOG] [LOG] [String in log:] This is a test string. This is another test string. [/LOG]