支持windows linux下将指定内存段转向16进制与ascii码的日志输出类

支持windows linux下将指定内存段转为16进制与ascii码的日志输出类

来源:http://blog.csdn.net/lezhiyong

1. 简介

   将指定内存段转为16进制与asci码的输出到日志文件的类。
2. 功能介绍
1) 支持window与linus双系统。
2) 可指定输出目录。
3) 日志能输出的时间精确到毫秒,日志能输出线程号。
4) 提供字符串输出。
5) 提供指定内存转换为16进制输出。
6) 提供指定内存转换为16进制和ascii码同时输出。
7) 可调整16进制输出间距。
3. 原理和算法
1) 模块是基于C++语言编写;
2) 通过条件定义同时支持window与linus双系统
4. 编译和链接
将源程序加入到工程中
5. 运行环境
windows、linux操作系统验证同时支持。
6. 限制条件

7. 接口
1.构造函数: CViTrace(char*szPathName,//路径名
char* szAppName,//文件名
_APP_INFO_OUT_CALLBACK pInfoOutCallback=NULL,//额外的输出回调
void *pInfoOutCallbackParam=NULL);//回调函数参数
/*************************************************************************************
功能:设置日志输出路径和额外的输出回调:
参数:
char*szPathName://路径名
char* szAppName,//文件名
_APP_INFO_OUT_CALLBACK pInfoOutCallback:额外的输出回调
**************************************************************************************/


3. UINT   trace(char* szFormat,...);
/*************************************************************************************
功能:字符串输出:
参数:
    char* szFormat:可变参数,类似printf的使用
**************************************************************************************/


4. trace_bin(char*pBuffer,UINT nLength,bool bPrintAsci=false)
/******************************************************************************************
功能:转换为16进制和ascii码输出:
参数:
void *Buf:内存片地址。
UINT nLength:内存片长度
bool bPrintAsci: false:左侧不输出ascii码信息,true:左侧输出ascii码信息
******************************************************************************************/


8. 示例
8.1. Linux Demo
#include "vitrace.h"
CViTrace vilog("/mds6800","1234");
vilog.trace("log out put demo,%s","string inf");
char* szName= "1234567asdfghddffgeerrtyuiopasdfgghhjjzxcvbbbnnnmn";
vilog.trace_bin(szName, 50);
vilog.trace_bin(szName, 100,true);


日志输出:
<2015-06-09,15:18:48-124, tId=134597956>log out put demo,string inf
<2015-06-09,15:18:48-124, tId=134597956>
 num address :bufferContent 
   0 0x807370c:31323334  35363761  73646667  68646466  66676565  72727479  75696F70  61736466  
  32 0x807372c:67676868  6A6A7A78  63766262  626E6E6E  6D6E                                    
<2015-06-09,15:18:48-124, tId=134597956>
 num address :bufferContent 
   0 0x807370c:31323334  35363761  73646667  68646466  66676565  72727479  75696F70  61736466  1234567asdfghddffgeerrtyuiopasdf
  32 0x807372c:67676868  6A6A7A78  63766262  626E6E6E  6D6E000D  0A20696E  70757420  77726F6E  gghhjjzxcvbbbnnnmn... input wron
  64 0x807374c:67212075  73616765  3A257320  25730000  0D0A2069  6E707574  2077726F  6E672120  g! usage:%s %s.... input wrong! 
  96 0x807376c:75736167                                                                        usag


8.2. Window Demo
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <string> 
#include <stdarg.h>
#include  <direct.h> 
#include "vitrace.h"
#include <windows.h>
#include <tchar.h>
#include "targetver.h"


char* szName= "1234567asdfghjklqwertyuiopasdfghjklzxcvbnm1234567asdfghjklqwertyuiopasdfghjklzxcvbnm";


int _tmain(int argc, _TCHAR* argv[])
{
char   buffer[MAX_PATH];   
getcwd(buffer, MAX_PATH); 
CViTrace viLog(buffer,"buffer_print_test");
viLog.trace("字符串信息输出:");
viLog.trace("that's why with other flash applications you just don't get the expected results.  the best option for each photo.");
viLog.trace("按进制编码输出指定内存的前字节内容:");
viLog.trace_bin(szName,50);
Sleep(100);
viLog.trace("输出指定内存的前字节内容,左边为进制值,右边为assci码:");
viLog.trace_bin(szName,100,true);
getchar();
return 0;
}


<2015-06-09,15:23:18-526, tId=20451738>字符串信息输出:
<2015-06-09,15:23:18-526, tId=20451738>that's why with other flash applications you just don't get the expected results.  the best option for each photo.
<2015-06-09,15:23:18-526, tId=20451738>按16进制编码输出指定内存的前300字节内容:
<2015-06-09,15:23:18-526, tId=20451738>
 num address :bufferContent 
   0 01387740:31323334  35363761  73646667  686A6B6C  71776572  74797569  6F706173  64666768  
  32 01387760:6A6B6C7A  78637662  6E6D3132  33343536  3761                                    
<2015-06-09,15:23:18-635, tId=20451738>输出指定内存的前1000字节内容,左边为16进制值,右边为assci码:
<2015-06-09,15:23:18-635, tId=20451738>
 num address :bufferContent 
   0 01387740:31323334  35363761  73646667  686A6B6C  71776572  74797569  6F706173  64666768  1234567asdfghjklqwertyuiopasdfgh
  32 01387760:6A6B6C7A  78637662  6E6D3132  33343536  37617364  6667686A  6B6C7177  65727479  jklzxcvbnm1234567asdfghjklqwerty
  64 01387780:75696F70  61736466  67686A6B  6C7A7863  76626E6D  00000000  00000000  00000000  uiopasdfghjklzxcvbnm............

  96 013877A0:00000000                                                 


/**
 * @file    Vitrace.h
 * @brief   支持windows linux下将指定内存段转为16进制与ascii码的日志输出类
 *
 * @writer  longf
 * @version 1.00
 * @date    2015-01-27
 * @history
*/
//#include "XAutoLock.h"
//#include "rcs_public.h"

#ifdef WIN32
#include <windows.h>
#else

#endif

#ifndef UINT
typedef unsigned int   UINT;         
#endif // UINT

#ifndef NULL
#define NULL 0         
#endif // NULL

#define MAX_PATH 512



UINT  vi_bin2ascii(char* pDstBuf,UINT nDstBufLen,char*pSrcBuf,UINT nSrcBufLen);
UINT  vi_bin2hex(char* pDstBuf,UINT nDstBufLen,char*pSrcBuf,UINT nSrcBufLen);


typedef void (*_APP_INFO_OUT_CALLBACK)(char*szInfo,void*pCallParam);

class  CViTrace
{
public:
	CViTrace(char*szPathName,//路径名
			char* szAppName,//文件名
			_APP_INFO_OUT_CALLBACK pInfoOutCallback=NULL,//额外的输出回调
			void *pInfoOutCallbackParam=NULL);//回调函数参数
	~CViTrace(void);
public:
	UINT   trace(char* szFormat,...);
	void   trace_bin(char*pBuffer,UINT nLength,bool bPrintAsci=false);
public:
    //方便应用层取出输出信息,在不同的输出设备打入自己的输出队列
	_APP_INFO_OUT_CALLBACK m_pInfoOutCallback;
	void* m_pInfoOutCallbackParam;
private:
	char		m_szFileName[MAX_PATH];//拼接好的路径名和文件名
	//XCritSec	m_Lock;
};


/**
 * @file    Vitrace.cpp
 * @brief   支持windows linux下将指定内存段转为16进制与ascii码的日志输出类
 *
 * @writer  longf
 * @version 1.00
 * @date    2015-01-27
 * @history
*/
#include "vitrace.h"
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
 #include <sys/time.h>
#endif


#ifdef CON_DEBUG
	#define CON_PRINTF printf 
#else
	#define CON_PRINTF/\
/printf
#endif


#ifdef WIN32
  #define PATH_CHAR "\\"
#else
  #define PATH_CHAR "/"
#endif


inline unsigned int PthreadSelf()
{
#ifdef WIN32
	return ::GetCurrentThreadId();
#else
	return pthread_self();
#endif
}

#define  VITRACE_BUFFER_LENGTH 10000  //TRACE缓冲区大小
#define  VITRACE_HEX_PRINTBYTES_PERLINE 32
#define  VITRACE_HEX_SPACE 4
static UINT safe_printf(char*pDst,UINT nDstSize,char*szFormat,...)
{
	UINT nListCount=0;
	va_list pArgList;
	if (!pDst) goto	 _EXIT_FUN;
	va_start(pArgList,szFormat);
	nListCount+=vsnprintf(pDst+nListCount,nDstSize-nListCount,szFormat,pArgList);
	va_end(pArgList);
	if (nListCount>(nDstSize-1)) nListCount = nDstSize-1;
	*(pDst+nListCount)='\0';
_EXIT_FUN:
	return nListCount;
}

void  GetFullFileName(char* pBufFullname,UINT nBufSize,char* path,char* name,char* ext_name)
{
	if (strlen(path))
	{
		if (strlen(ext_name))
			safe_printf(pBufFullname,nBufSize,
			"%s%s%s.%s",path,PATH_CHAR,name,ext_name);
		else     	 
			safe_printf(pBufFullname,nBufSize,
			"%s%s%s",path,PATH_CHAR,name,name);
	} 
	else
	{
		if (strlen(ext_name))
			safe_printf(pBufFullname,nBufSize,
			"%s.%s",name,ext_name);
		else    
			safe_printf(pBufFullname,nBufSize,
			"%s",name);
	}
}

UINT get_timestamp(char* szBuf,UINT nMaxLength)
{
	UINT nLength=0;
   #ifdef WIN32
	 SYSTEMTIME tm;
	 GetLocalTime(&tm);
	 nLength= safe_printf(szBuf,nMaxLength,"%02d-%02d-%02d,%02d:%02d:%02d-%03d",tm.wYear,tm.wMonth,tm.wDay,tm.wHour,tm.wMinute,tm.wSecond,tm.wMilliseconds );
   #else
	/*
	time_t t;
	struct tm*pTM=NULL;
	time(&t);
	pTM= localtime(&t);
	nLength= safe_printf(szBuf,nMaxLength,"%s",asctime(pTM)); 
	*/
	struct timeval    tv;  
	struct timezone tz;  
	struct tm         *p;  
	gettimeofday(&tv, &tz);  
	p = localtime(&tv.tv_sec);  
	nLength= safe_printf(szBuf,nMaxLength,"%02d-%02d-%02d,%02d:%02d:%02d-%03d", 1900+p->tm_year, 1+p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, tv.tv_usec/1000);
   #endif
   return nLength;
}


////以ascii显示指定数据区内容
UINT  vi_bin2ascii(char* pDstBuf,UINT nDstBufLen,char*pSrcBuf,UINT nSrcBufLen)
{
	if (nSrcBufLen>nDstBufLen)
	{
	   nSrcBufLen = nDstBufLen;	 
	}
	UINT i;
	UINT nCount=0;
	for (i=0;i<nSrcBufLen;i++)
	{
		//ascii字符表中可显示字符代码>32
		if (32<=*(pSrcBuf+i))
		{
			nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,"%c",pSrcBuf[i]);
		}
		else
		{
			nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,".");
		}
	}
	return nCount;
}

//以16进制显示指定数据区内容
UINT  vi_bin2hex(char* pDstBuf,UINT nDstBufLen,char*pSrcBuf,UINT nSrcBufLen)
{
	if (nSrcBufLen>nDstBufLen)
	{
		nSrcBufLen = nDstBufLen;	 
	}
	UINT i=0;
	UINT j=0;
	UINT nCount=0;
	for (i=0;i<nSrcBufLen;i++)
	{
		nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,"%02X",(unsigned char)pSrcBuf[i]);
		j++;
		if (VITRACE_HEX_SPACE==j)
		{
			j=0;
			nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,"  ");
		}
	}
	if (VITRACE_HEX_PRINTBYTES_PERLINE>nSrcBufLen)//每行打印VITRACE_PRINTBYTES_PER_LINE字节,不足补充空格
	{
		for (;i<VITRACE_HEX_PRINTBYTES_PERLINE;i++)
		{
			nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,"  ");//一个字符占用两个字节
			j++;
			if (VITRACE_HEX_SPACE==j)
			{
				j=0;
				nCount+= safe_printf(pDstBuf+nCount,nDstBufLen-nCount,"  ");
			}
		}
	}
    return nCount;
}

//用户指定的输出文件,文件打开方式,一般“a+”,返回输出字符总数
UINT vi_trace(char* szFileName,char*szMode,char*strBuf)
{
	UINT nListCount =0;
	char szTime[256];
	get_timestamp(szTime,256);
	char tmp[VITRACE_BUFFER_LENGTH+256];
	sprintf(tmp, "\r\n<%s, tId=%d>",szTime,PthreadSelf);
	FILE* fp;
	fp=fopen(szFileName,szMode);
	if (fp)
	{
		nListCount += fwrite(tmp, strlen(tmp), 1, fp);	
	}

    nListCount +=  fwrite(strBuf, strlen(strBuf), 1, fp);
    fclose(fp);
	return nListCount;
}

/*
Vint32 vi_trace(char* szFileName,char*szMode,char*szFormat,...)
{
	char szBuf[LODEBUG_BUFFER_LENGTH];
	char szTime[256];
	Vint32 nListCount=0;
	va_list pArgList;
	va_start(pArgList,szFormat);
	nListCount+=_vsnprintf(szBuf+nListCount,LODEBUG_BUFFER_LENGTH-nListCount,szFormat,pArgList);
	va_end(pArgList);
	if (nListCount>(LODEBUG_BUFFER_LENGTH-1))
	{
		nListCount=LODEBUG_BUFFER_LENGTH-1;
	}
	*(szBuf+nListCount)='\0';
    nListCount = vi_trace(szFileName,szMode,szBuf); 
	return nListCount;
}
*/
//调用函数,VITRACE_HEX_PRINTBYTES_PERLINE字节为一行,格式化输出二进制内容
void vi_trace_bin(char* szFileName,char*szMode,char*pBuffer,UINT nLength,bool bPrintAsci=false)
{
	if (nLength>VITRACE_BUFFER_LENGTH)
	{
         nLength =VITRACE_BUFFER_LENGTH;
	}
	int nAddr=0;
	int nLineValidCount=0;
	int nLineSpaceCount=0;
	int nBufferCount =nLength;
	int n=0;
	char szLine[VITRACE_BUFFER_LENGTH+1]={0};
	int iLineNum=0;
	if(0<nLength)
	{
		n+=safe_printf(szLine+n,VITRACE_BUFFER_LENGTH-n,"\r\n%4s %8s:%s","num","address ","bufferContent ");	
		if (bPrintAsci)
		{
			n+=vi_bin2ascii(szLine+n,VITRACE_BUFFER_LENGTH-n,pBuffer+nAddr,nLineValidCount);
		}
		while (1)
		{
			if (nBufferCount>=VITRACE_HEX_PRINTBYTES_PERLINE)
			{
			    nLineValidCount = VITRACE_HEX_PRINTBYTES_PERLINE;
				nLineSpaceCount = 0;
			}
			else
			{
				nLineValidCount = nBufferCount;
				nLineSpaceCount =  VITRACE_HEX_PRINTBYTES_PERLINE- nLineValidCount;     
			}
			n+=safe_printf(szLine+n,VITRACE_BUFFER_LENGTH-n,"\r\n%4d %p:",iLineNum*VITRACE_HEX_PRINTBYTES_PERLINE,pBuffer+nAddr);		
			n+=vi_bin2hex(szLine+n,VITRACE_BUFFER_LENGTH-n,pBuffer+nAddr,nLineValidCount);
			if (bPrintAsci)
			{
				n+=vi_bin2ascii(szLine+n,VITRACE_BUFFER_LENGTH-n,pBuffer+nAddr,nLineValidCount);
			}
			nAddr+=VITRACE_HEX_PRINTBYTES_PERLINE;
			nBufferCount-=VITRACE_HEX_PRINTBYTES_PERLINE;
			iLineNum++;
			if (0>=nBufferCount) break;
		}
	}
	vi_trace(szFileName,szMode,szLine);
}

/*************************************************************************************
功能:设置日志输出路径和额外的输出回调:
参数:
char*szPathName://路径名
char* szAppName,//文件名
_APP_INFO_OUT_CALLBACK pInfoOutCallback:额外的输出回调
**************************************************************************************/

CViTrace::CViTrace(char*szPathName,char* szAppName,_APP_INFO_OUT_CALLBACK pInfoOutCallback, void *pInfoOutCallbackParam)
{
	m_pInfoOutCallback=pInfoOutCallback;
	m_pInfoOutCallbackParam=pInfoOutCallbackParam;
	if (szAppName)
	{
		GetFullFileName(m_szFileName,MAX_PATH,szPathName,szAppName,"log");
	}
	else
		m_szFileName[0]='\0';
	remove(m_szFileName);
}

CViTrace::~CViTrace(void)
{

}
/*************************************************************************************
功能:字符串输出:
参数:
    char* szFormat:可变参数,类似printf的使用
**************************************************************************************/

UINT CViTrace::trace(char* szFormat,...)
{
   //XAutoLock xLock(m_Lock);
	char szBuff[VITRACE_BUFFER_LENGTH]={0};
	FILE *fp=NULL;
	UINT nListCount=0;
	va_list pArgList;
  
	va_start(pArgList,szFormat);
	nListCount+= vsnprintf(szBuff+nListCount,VITRACE_BUFFER_LENGTH-nListCount,szFormat,pArgList);
	va_end(pArgList);
	if (nListCount>(VITRACE_BUFFER_LENGTH-1))
	{
		nListCount = VITRACE_BUFFER_LENGTH-1;
	}
	*(szBuff+nListCount)='\0';
	nListCount = vi_trace(m_szFileName,"a+",szBuff);
	//回调输出;
	if(m_pInfoOutCallback)
	{
		char szTime[256];
		get_timestamp(szTime,256);
		char tmp[256];
		sprintf(tmp, "\r\n<%s, tId=%d>\t",szTime,PthreadSelf);
		char szInfoOut[VITRACE_BUFFER_LENGTH];
		safe_printf(szInfoOut,VITRACE_BUFFER_LENGTH,"%s%s",tmp,szBuff);
		m_pInfoOutCallback(szInfoOut,m_pInfoOutCallbackParam);
		//CON_PRINTF("%s",szInfoOut);	
	}
	return nListCount;
}
/******************************************************************************************
功能:转换为16进制和ascii码输出:
参数:
	void *Buf:内存片地址。
UINT nLength:内存片长度
bool bPrintAsci: false:左侧不输出ascii码信息,true:左侧输出ascii码信息
******************************************************************************************/

void CViTrace::trace_bin(char*pBuffer,UINT nLength,bool bPrintAsci)
{
	if (nLength>1000)
	{
		 nLength = 1000;
	}
	//XAutoLock xLock(m_Lock);
	vi_trace_bin(m_szFileName,"a+",pBuffer,nLength,bPrintAsci);
}






版权声明:本文为博主原创文章,未经博主允许不得转载。