/*
*Name : log.h
*Author : windcao
*Version : 1.0
*Copyright : windcao@people.com.cn 2009
*Description : Log.h
*add into you mmp:
*LIBRARY flogger.lib
*
*USING:
*on your emulater:
*if using winscw create dir epocroot\winscw\c\logs\[YOUR_DIR_NAME]\
*for example:
* C:\Symbian\8.0a\S60_2nd_FP2_CW\Epoc32\winscw\c\logslogs\L\
*
*if using wins create dir epocroot\wins\c\logs\[YOUR_DIR_NAME]\
*for example:
* C:\Symbian\8.0a\S60_2nd_FP2_CW\Epoc32\winscw\c\logslogs\L\
*
*if using mobile create dir c:\logs\[YOUR_DIR_NAME]\
*for example:
* c:\logs\L\
*
* the log file will be created auto.At the first time to be write.
*
*EXAMPLE:
*
*/
#ifndef __LOG_H__
#define __LOG_H__
#include
#include
void log_printf(TRefByValue aFmt, ...);
void log_printf(RFileLogger* aLoger, TRefByValue aFmt, ...);
void log_printf(const TDesC& aFileName, TRefByValue aFmt, ...);
void log_printf(const TDesC& aDir, const TDesC& aFileName,
TRefByValue aFmt, ...);
// define level
#ifdef __USING_LOG__
#define LOG_DECLARE(LOGGER) RFileLogger NAME;
#define LOG_OPEN(LOGGER,DIR_NAME,FILE_NAME) {LOGGER.Connect();LOGGER.CreateLog(DIR_NAME,FILE_NAME,EFileLoggingModeAppend);}
#define LOG_CLOSE(LOGGER) { LOGGER.CloseLog();LOGGER.Close();}
#define LOG_PRINTF log_printf
#define LOG_I(LOGGER_PTR,VAR) {TInt _Temp = VAR;LOG_PRINTF(LOGGER_PTR,_L(#VAR ## "=%d"),_Temp);}
#define LOG_HEX_I(LOGGER_PTR,VAR) {TInt _Temp = VAR;LOG_PRINTF(LOGGER_PTR,_L(#VAR ## "=0x%x"),_Temp);}
#define LOG_U(LOGGER_PTR,VAR) {TUint _Temp = VAR;LOG_PRINTF(LOGGER_PTR,_L(#VAR ## "=%u"),_Temp);}
#define LOG_D(LOGGER_PTR,DESC) log_printf(LOGGER_PTR,_L(#DESC ## "len=%d,buf=%S"),DESC.Length(),&(DESC))
#define LOG_D_PTR(LOGGER_PTR,DESC_PTR) log_printf(LOGGER_PTR,_L(#DESC_PTR ## "len=%d,buf=%S"),DESC_PTR->Length(),DESC_PTR)
#define LOG_INT(VAR) {TInt _Temp = VAR;LOG_PRINTF(_L(#VAR ## "=%d"),_Temp);}
#define LOG_HEX_INT(VAR) {TInt _Temp = VAR;LOG_PRINTF(_L(#VAR ## "=0x%x"),_Temp);}
#define LOG_UINT(VAR) {TUint _Temp = VAR;LOG_PRINTF(_L(#VAR ## "=%u"),_Temp);}
#define LOG_DESC(DESC) log_printf(_L(#DESC ## "len=%d,buf=%S"),DESC.Length(),&(DESC))
#define LOG_DESC_PTR(DESC_PTR) log_printf(_L(#DESC_PTR ## "len=%d,buf=%S"),DESC_PTR->Length(),DESC_PTR)
#else // __USING_LOG__
#define LOG_DECLARE(NAME)
#define LOG_OPEN(NAME)
#define LOG_CLOSE(NAME)
#define LOG_PRINTF
#define LOG_I(LOGGER_PTR,VAR)
#define LOG_HEX_I(LOGGER_PTR,VAR)
#define LOG_U(LOGGER_PTR,VAR)
#define LOG_D(LOGGER_PTR,VAR)
#define LOG_D_PTR(LOGGER_PTR,VAR)
#define LOG_INT(VAR)
#define LOG_HEX_INT(VAR)
#define LOG_UINT(VAR)
#define LOG_DESC(VAR)
#define LOG_DESC_PTR(VAR)
#endif // __USING_LOG__
#endif // __LOG_H__
class TLogFmtOverflow : public TDesOverflow
{
void Overflow(TDes& aDes)
{
iIsOverflowed = ETrue;
iMaxDesLen = aDes.MaxLength();
}
public:
void Reset()
{
iIsOverflowed = EFalse;
iMaxDesLen = 0;
}
public:
TBool iIsOverflowed;
TInt iMaxDesLen;
};
实现:
/*
*Name : log.cpp
*Author : windcao
*Version : 1.0
*Copyright : windcao@people.com.cn 2009
*Description : Log impl */
#include "log.h"
#include
_LIT(KDefaultDir,"Logs");
_LIT(KDefaultFileName,"app.log");
const TInt KPredictiveFormatIncrementLen = 1024;
const TInt KMaxWCharLineLen = 42;
const TInt KMaxNCharLineLen = 128;
//处理可变参数
static void _log_printf(const TDesC& aDir, const TDesC& aFileName,
const TDesC &aFmt, VA_LIST& aList, RFileLogger* aLoger = NULL);
//从指定区间内的unicode字符串内匹配一个最长的子串,这个子串转换成utf8后不超出固定的长度
//aUCS2Ptr unicode字符串,
//aFrom 在aUCS2Ptr里面的 第aFrom开始匹配直到长度超过aLeftLength
//aUtfBufSizeToBeFit 要求转化为utf8后长度不超过aUtfBufSizeToBeFit
static TInt UnicodeLenthFitUtf8Size(const TUint16* aUCS2Ptr, TInt aFrom,
TInt aLeftLength, TInt aUtfBufSizeToBeFit);
void log_printf(TRefByValue aFmt, ...)
{
VA_LIST ap;
VA_START(ap,aFmt);
_log_printf(KDefaultDir, KDefaultFileName, aFmt, ap, NULL);
VA_END(ap);
}
void log_printf(RFileLogger* aLogger, TRefByValue aFmt, ...)
{
VA_LIST ap;
VA_START(ap, aFmt);
_log_printf(KDefaultDir, KDefaultFileName, aFmt, ap, aLogger);
VA_END(ap);
}
void log_printf(const TDesC& aFileName, TRefByValue aFmt, ...)
{
VA_LIST ap;
VA_START(ap, aFmt);
_log_printf(KDefaultDir, aFileName, aFmt, ap);
VA_END(ap);
}
void log_printf(const TDesC& aDir, const TDesC& aFileName, TRefByValue<
const TDesC> aFmt, ...)
{
VA_LIST ap;
VA_START(ap, aFmt);
_log_printf(aDir, aFileName, aFmt, ap);
VA_END(ap);
}
void _log_printf(const TDesC& aDir, const TDesC& aFileName, const TDesC &aFmt,
VA_LIST& aList, RFileLogger* aLogger)
{
/// add by Smart Man:
/// To work at symbian os envirnmont
/// set the format string
TInt buf_size = ((const TDesC) aFmt).Length();
if (buf_size <= 0)
return;
TInt bufLen = buf_size;
HBufC* logInfoHeap = NULL;
TLogFmtOverflow logfmtof;
do
{
logfmtof.Reset();
bufLen += KPredictiveFormatIncrementLen;
logInfoHeap = HBufC::New(bufLen + 1);
logInfoHeap->Des().AppendFormatList(aFmt, aList, &logfmtof);
if (!logfmtof.iIsOverflowed)
{
break;
}
delete logInfoHeap;
} while (logfmtof.iIsOverflowed);
// wirte logs to log file.
TInt leftLen = logInfoHeap->Length();
TInt from = 0;
TBool stopTimeLog = EFalse;
//把超长的拆成短的。既要尽可能长又不能截断中文。这里面很复杂。
//我们现在有点是一个uicode字符串,而我们要确保拆分完后转成utf8后总长度不超过128字节。
while (leftLen > 0)
{
if (aLogger && leftLen != logInfoHeap->Length())
{
aLogger->SetDateAndTime(EFalse, EFalse);
stopTimeLog = ETrue;
}
TPtrC currentLine;
if (leftLen <= KMaxWCharLineLen)//这就是说肯定一行可以搞定
{
currentLine.Set(logInfoHeap->Des().Mid(from));
leftLen = 0;
}
else//还可能需要继续拆分
{
TInt maxLineLen = (stopTimeLog) ? KLogBufferSize - 2 : KMaxNCharLineLen;
TInt lineLen = UnicodeLenthFitUtf8Size(logInfoHeap->Ptr(), from,
leftLen, maxLineLen);
currentLine.Set(logInfoHeap->Des().Mid(from, lineLen));
from += lineLen;
leftLen -= lineLen;
}
if (aLogger)
{
aLogger->Write(currentLine);
TInt lerr = aLogger->LastError();
if (lerr)
{
_LIT(KErrFmt,"Err = %d");
RFileLogger::WriteFormat(aDir, aFileName,
EFileLoggingModeAppend, KErrFmt(), lerr);
}
}
else
RFileLogger::Write(aDir, aFileName, EFileLoggingModeAppend,
currentLine);
}
if (stopTimeLog)
aLogger->SetDateAndTime(ETrue, ETrue);
delete logInfoHeap;
}
//从指定区间内的unicode字符串内匹配一个最长的子串,这个子串转换成utf8后不超出固定的长度
TInt UnicodeLenthFitUtf8Size(const TUint16* aUCS2Ptr, TInt aFrom, TInt aLeftLength,
TInt aUtfBufSizeToBeFit)
{
TInt result = 0;
TUint16 * current = const_cast (aUCS2Ptr) + aFrom;
TInt size_d = 0;
while (aLeftLength > 0 && aUtfBufSizeToBeFit > size_d)
{
if ((*current) < 0x80)
{ //lenght = 1
aLeftLength--;
result++;
size_d++;
}
else if ((*current) < 0x800)
{
//length = 2;
if (aUtfBufSizeToBeFit >= size_d + 2)
{
aLeftLength--;
result++;
size_d += 2;
}
else
aLeftLength = 0;
}
else //if ((*current) < 0x10000)
{
//length = 3;
if (aUtfBufSizeToBeFit >= size_d + 3)
{
aLeftLength--;
result++;
size_d += 3;
}
else
aLeftLength = 0;
}
current++;
}
return result;
}
测试程序:
#include "Log.h"
_LIT(KTestMaxLenCS,"\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x31\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x32\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x33\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x34\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x35\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x36\x9996\x5148\x6211\x4eec\x6d4b\x8bd5\x4e00\x4e0b\x7cfb\x7edf\x7684\x52\x4c\x6f\x67\x67\x65\x72\x7684\x6700\x5927\x957f\x5ea6\xff0c\x6d4b\x8bd5\x5757\x30\x30\x37");//首先我们测试一下系统的RLogger的最大长度,测试块001首先我们测试一下系统的RLogger的最大长度,测试块002首先我们测试一下系统的RLogger的最大长度,测试块003首先我们测试一下系统的RLogger的最大长度,测试块004首先我们测试一下系统的RLogger的最大长度,测试块005首先我们测试一下系统的RLogger的最大长度,测试块006首先我们测试一下系统的RLogger的最大长度,测试块007
_LIT(KTestMaxLenEN,"TestTheMAXLengthOFRLogger,testTheLenUseThisLoop001TestTheMAXLengthOFRLogger,testTheLenUseThisLoop002TestTheMAXLengthOFRLogger,testTheLenUseThisLoop003TestTheMAXLengthOFRLogger,testTheLenUseThisLoop004TestTheMAXLengthOFRLogger,testTheLenUseThisLoop005TestTheMAXLengthOFRLogger,testTheLenUseThisLoop006TestTheMAXLengthOFRLogger,testTheLenUseThisLoop007");
_LIT(KMaxLenTestSC2,"\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x4e00\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x4e8c\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x4e09\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x56db\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x4e94\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x516d\x6700\x5927\x957f\x5ea6\x6d4b\x8bd5\x7eaf\x4e2d\x6587\x65e0\x6df7\x5408\x7684\x60c5\x51b5\x4e0b\x4e5f\x6ca1\x6709\x6807\x70b9\x5757\x96f6\x96f6\x4e03");//最大长度测试纯中文无混合的情况下也没有标点块零零一最大长度测试纯中文无混合的情况下也没有标点块零零二最大长度测试纯中文无混合的情况下也没有标点块零零三最大长度测试纯中文无混合的情况下也没有标点块零零四最大长度测试纯中文无混合的情况下也没有标点块零零五最大长度测试纯中文无混合的情况下也没有标点块零零六最大长度测试纯中文无混合的情况下也没有标点块零零七
_LIT(KTestDesc,"Test Desc log");
_LIT(KTestDescChinese,"\x4e2d\x6587");//中文
_LIT(KFmt,"KTestDesc()len=%d,buf=%S");
_LIT(KDir,"Lichao");
_LIT(KFile,"123.log");
下面这段放在函数中:
TInt i=KMaxTInt;
TUint ui = KMaxTInt;
RFileLogger iLog;
LOG_OPEN(iLog,KDir(),KFile());
LOG_PRINTF(&iLog,_L("------------------[Test member methods]------------------"));
LOG_PRINTF(&iLog,_L("------------------[1][Test Int]------------------"));
LOG_I(&iLog,i);
LOG_HEX_I(&iLog,i);
LOG_U(&iLog,i);
LOG_I(&iLog,ui);
LOG_HEX_I(&iLog,ui);
LOG_U(&iLog,ui);
//看看宏定义是否会带来问题:
LOG_PRINTF(&iLog,_L("test m_print ++i:%d"),++i);
LOG_PRINTF(&iLog,_L("test m_print ++i:%d"),++i);
LOG_PRINTF(&iLog,_L("test m_print ++i:%d"),++i);
LOG_PRINTF(&iLog,_L("test m_print ++i:%d"),++i);
LOG_I(&iLog,++i);
LOG_HEX_I(&iLog,++i);
LOG_U(&iLog,++i);
LOG_I(&iLog,++ui);
LOG_HEX_I(&iLog,++ui);
LOG_U(&iLog,++ui);
//看看字符处理是否正确:
LOG_PRINTF(&iLog,_L("------------------[2][Test Des]------------------"));
LOG_D(&iLog,KTestDesc());
LOG_D(&iLog,KTestDesc().Mid(4));
LOG_D(&iLog,KTestDescChinese());
LOG_D(&iLog,KTestMaxLenCS());
LOG_D(&iLog,KTestMaxLenEN());
_LIT(KTestDesc,"Test Desc log");
LOG_PRINTF(&iLog,_L("%S the m_print en END"),&(KTestMaxLenEN()));
LOG_PRINTF(&iLog,_L("%S the m_print cn END"),&(KTestMaxLenCS()));
LOG_CLOSE(iLog);
这是我从网上找的,我试了试比较好使,放在这里希望对更多的人有所帮助!
注意:
第一,要在 mmp 文件中加入 flogger.lib 库文件
第二,在 mmp 文件中引入宏 MACRO __USING_LOG__
第三,要生成日志文件,需要在你的SDK环境下建相应的目录。它的默认目录为: SDK环境下的 C:\LOGS\。例如,你要将日志文件放入 APPLOG 这个目录下,那么你就要在 C 盘下建 LOGS 目录,然后在LOGS目录下建 APPLOG 这个目录。