int CTonyLowDebug::Debug2File(char *szFormat, ...) { //注意,这个类设计时,还没有内存池概念,因此,动态内存申请,原则上应该避免 //以免出现内存碎片。此处使用静态数组实现buffer,在浮动栈建立。 //这也是为什么这个类必须声明最大输出字符串长度的原因 char szBuf[DEBUG_BUFFER_LENGTH]; //准备输出buffer char szTemp[DEBUG_BUFFER_LENGTH]; //时间戳置换的中间buffer char szTime[DEBUG_BUFFER_LENGTH]; //时间戳的buffer FILE* fp = NULL; //文件指针,以C 模式工作 int nListCount = 0; va_list pArgList; time_t t; struct tm *pTM = NULL; int nLength = 0; //这是构建时间戳 time(&t); pTM = localtime(&t); nLength = SafePrintf(szTemp, DEBUG_BUFFER_LENGTH, "%s", asctime(pTM)); szTemp[nLength - 1] = '\0'; SafePrintf(szTime, DEBUG_BUFFER_LENGTH, "[%s] ", szTemp); //注意,此处开始进入加锁,以此保证跨线程调用安全 m_Lock.Lock(); { //习惯性写法,以大括号和缩进清晰界定加锁区域,醒目。 //下面这个段落是从SafePrintf 拷贝出来的,一个逻辑的可重用性, //也可以根据需要,直接拷贝代码段实现,不一定非要写成宏或函数。 va_start(pArgList, szFormat); nListCount += Linux_Win_vsnprintf(szBuf + nListCount, DEBUG_BUFFER_LENGTH - nListCount, szFormat, pArgList); va_end(pArgList); if (nListCount > (DEBUG_BUFFER_LENGTH - 1)) nListCount = DEBUG_BUFFER_LENGTH - 1; *(szBuf + nListCount) = '\0'; //开始真实的输出 fp = fopen(m_szFileName, "a+"); //请注意下面逻辑,由于本函数使用了锁,因此只能有一个退出点 //这里笔者没有使用goto,因此,必须使用if 嵌套,确保不会中间跳出 if (fp) { //输出到文件 nListCount = fprintf(fp, "%s%s", szTime, szBuf); if (m_bPrint2TTYFlag) { //根据需要输出至控制台 TONY_PRINTF("%s%s", szTime, szBuf); if (m_pInfoOutCallback) { //注意此处,回调输出给需要的上层调用 //注意,本段为后加,没有使用前文变量,目前是减少bug 率 char szInfoOut[APP_INFO_OIT_STRING_MAX]; SafePrintf(szInfoOut, APP_INFO_OIT_STRING_MAX, "%s%s", szTime, szBuf); m_pInfoOutCallback(szInfoOut, //注意把输出字符串传给回调 m_pInfoOutCallbackParam); //透传的指针 } } fclose(fp); } else { nListCount = 0; } } m_Lock.Unlock(); //解锁 return nListCount; //返回输出的字节数,所有字符串构造和输出函数的习惯 }
int CTonyXiaoLog::_Printf(char *szFormat, ...) { char szTime[LOG_ITEM_LENGTH_MAX]; char szTemp[LOG_ITEM_LENGTH_MAX]; char szBuf[LOG_ITEM_LENGTH_MAX]; int nMaxLength = LOG_ITEM_LENGTH_MAX; int nListCount = 0; time_t t; struct tm *pTM = NULL; int nLength = 0; //获得当前时间戳,这在MakeATimeString 中已经有介绍 time(&t); pTM = localtime(&t); nLength = SafePrintf(szTemp, LOG_ITEM_LENGTH_MAX, "%s", asctime(pTM)); szTemp[nLength - 1] = '\0'; SafePrintf(szTime, LOG_ITEM_LENGTH_MAX, "[%s] ", szTemp); //这段比较经典,变参函数处理模块,不再赘述 va_list pArgList; va_start(pArgList, szFormat); nListCount += Linux_Win_vsnprintf(szBuf + nListCount, nMaxLength - nListCount, szFormat, pArgList); va_end(pArgList); if (nListCount > (nMaxLength - 1)) nListCount = nMaxLength - 1; *(szBuf + nListCount) = '\0'; //得到当前使用的文件名 GetFileName(); //调用debug 的功能函数,直接将信息输出到文件 nListCount = dbg2file(m_szFileName, "a+", "%s%s", szTime, szBuf); if (m_bPrintf2ScrFlag) //如果屏幕输出开关打来 { TONY_XIAO_PRINTF("%s%s", szTime, szBuf); //输出到屏幕 } if (m_pInfoOutCallback) //如果拦截函数存在 { //输出到拦截函数 char szInfoOut[APP_INFO_OIT_STRING_MAX]; SafePrintf(szInfoOut, APP_INFO_OIT_STRING_MAX, "%s%s", szTime, szBuf); m_pInfoOutCallback(szInfoOut, m_pInfoOutCallbackParam); } m_nFileSize += nListCount; //这里很重要,修订文件长度 //维护模块需要这个值判定文件大小 //是否超标 return nListCount; //返回输出的字节数 }
int CNEOLog::_Printf(const char *szFormat,...) { char szTime[LOG_ITEM_LENGTH_MAX] = {"\0"}; char szTemp[LOG_ITEM_LENGTH_MAX] = {"\0"}; char szBuf[LOG_ITEM_LENGTH_MAX] = {"\0"}; int nMaxLength=LOG_ITEM_LENGTH_MAX; int nListCount=0; time_t t; struct tm *pTM=NULL; int nLength=0; time(&t); pTM=localtime(&t); nLength=SafePrintf(szTemp,LOG_ITEM_LENGTH_MAX,"%s",asctime(pTM)); szTemp[nLength-1]='\0'; SafePrintf(szTime,LOG_ITEM_LENGTH_MAX,"[%s]",szTemp); va_list pArgList; va_start(pArgList,szFormat); nListCount+=WIN_LINUX_vsnprintf(szBuf+nListCount,nMaxLength-nListCount,szFormat,pArgList); va_end(pArgList); if(nListCount>(nMaxLength-1)) nListCount=nMaxLength-1; *(szBuf+nListCount)='\0'; //得到当前的文件名 GetFileName(); //将信息输出到文件 nListCount=OutputFileOrScreen(m_szFileName,"a+","%s%s",szTime,szBuf); if(m_bPrintfToScrFlag) { NEO_PRINTF("%s%s",szTime,szBuf); } if(m_pInfoOutCallback) { char szInfoOut[APP_INFO_OIT_STRING_MAX]; SafePrintf(szInfoOut,APP_INFO_OIT_STRING_MAX,"%s%s",szTime,szBuf); m_pInfoOutCallback(szInfoOut,m_pInfoOutCallbackParam); } m_nFileSize+=nListCount; return nListCount; }