c++ 日志操作
程序需要一个简单的日志类,为此简单学习了Boost.Log和google的glog,前者功能非常强大,后者非常小巧但是不够灵活,最终打算自己写一个。
环境:
win7 32位旗舰版、VS2010旗舰版
TinyLog.h文件
#ifndef _TINY_LOG_H_
#define _TINY_LOG_H_ #include <fstream>
#include <list>
#include <string> #define _WINDOWS namespace TinyLogHelper
{
template<typename T>
T GetCurrentDir()
{
} #ifdef _WINDOWS #include <windows.h> //////////////////////////////////////////////////////////////////////////
// 线程互斥锁
//////////////////////////////////////////////////////////////////////////
class CLock
{
public:
CLock()
{
InitializeCriticalSection(&m_cs);//初始化临界区
} ~CLock()
{
DeleteCriticalSection(&m_cs);//删除临界区
} void Lock()
{
EnterCriticalSection(&m_cs);//加锁
} void UnLock()
{
LeaveCriticalSection(&m_cs);//解锁
} private:
CRITICAL_SECTION m_cs;
}; //////////////////////////////////////////////////////////////////////////
// 函数功能:
// 获取当前目录
//////////////////////////////////////////////////////////////////////////
template<>
std::string GetCurrentDir<std::string>(); template<>
std::wstring GetCurrentDir<std::wstring>(); #endif
} namespace TinyLog
{
//////////////////////////////////////////////////////////////////////////
// CTinyLog类修改记录
// 2014-5-24
// 使用m_nLogBufferLength记录当前日志缓存的大小,而不使用GetLogBufferSize
// 函数将整个日志缓存遍历一次来获取,提高运行速度。
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// 日志等级
// LogLevelDebug等级,会输出所有日志信息
// LogLevelInfo等级,会输出INFO日志信息
// LogLevelError等级,会输出ERROR日志信息
//////////////////////////////////////////////////////////////////////////
enum LogLevel
{
LogLevelDebug,//调试
LogLevelInfo,//信息
LogLevelError,//错误
}; const static char* pszLogLevelString[3] = {
"Debug",
"Info",
"Error"
}; //////////////////////////////////////////////////////////////////////////
// 类说明:
// 单线程日志类,应该只在一个线程中操作日志
//////////////////////////////////////////////////////////////////////////
template<typename T>
class CTinyLog
{ }; template<>
class CTinyLog<char>
{
public:
CTinyLog(); ~CTinyLog(); public:
//添加日志记录
CTinyLog& operator <<(const char* pszMessage); //添加调试日志
void Debug(const char* pszMessage); //添加信息日志
void Info(const char* pszMessage); //添加错误日志
void Error(const char* pszMessage); //将日志缓存写入到文件中
CTinyLog& WriteToFile(); //得到第一个写入文件路径
std::string GetFirstWriteFilePath() const; //得到下一个写入文件路径
std::string GetNextWriteFilePath() const; //得到文件路径格式
std::string GetCurrentFilePathFormat() const; public://属性
//设置文件
bool SetFileDir(const std::string& strFileDir); //设置文件扩展名
bool SetFillExtendName(const std::string& strFileExtendName); //设置文件名称格式
bool SetFileNameFormat(const std::string& strFileNameFormat); //设置最大文件大小(字节)
void SetMaxFileSize(std::size_t size); //设置最大写入文件大小(字节)
void SetMaxWriteFileSize(std::size_t size); //设置最大文件个数
void SetMaxFileCount(std::size_t count); //设置日志等级
void SetLogLevel(LogLevel emLogLevel); private:
//日志缓存
std::list<std::string> m_lstLogBuffer; std::string m_strFileDir;//文件目录
std::string m_strFileExtendName;//文件扩展名
std::string m_strFileNameFormat;//文件名格式 std::size_t m_nMaxFileSize;//最大文件大小(字节)
std::size_t m_nMaxWriteFileSize;//最大写入文件大小(字节)
mutable std::size_t m_nFileIndex;//文件索引
std::size_t m_nFileCount;//文件最大个数 LogLevel m_emLogLevel;//日志等级 std::size_t m_nLogBufferLength;//日志缓存长度(字节)
}; template<>
class CTinyLog<wchar_t>
{ }; //////////////////////////////////////////////////////////////////////////
// 类说明:
// 多线程日志类,可以在多个线程中操作日志
//////////////////////////////////////////////////////////////////////////
template<typename T>
class CTinyLogM
{ }; template<>
class CTinyLogM<char>
{
public:
CTinyLogM(); ~CTinyLogM(); public:
//添加日志记录
CTinyLogM& operator <<(const char* pszMessage); //添加调试日志
void Debug(const char* pszMessage); //添加信息日志
void Info(const char* pszMessage); //添加错误日志
void Error(const char* pszMessage); //将日志缓存写入到文件中
CTinyLogM& WriteToFile(); //得到第一个写入文件路径
std::string GetFirstWriteFilePath() const; //得到下一个写入文件路径
std::string GetNextWriteFilePath() const; //得到文件路径格式
std::string GetCurrentFilePathFormat() const; public://属性
//设置文件目录
bool SetFileDir(const std::string& strFileDir); //设置文件扩展名
bool SetFillExtendName(const std::string& strFileExtendName); //设置文件名称格式
bool SetFileNameFormat(const std::string& strFileNameFormat); //设置最大文件大小(字节)
void SetMaxFileSize(std::size_t size); //设置最大写入文件大小(字节)
void SetMaxWriteFileSize(std::size_t size); //设置最大文件个数
void SetMaxFileCount(std::size_t count); //设置日志等级
void SetLogLevel(LogLevel emLogLevel); private:
//日志缓存
std::list<std::string> m_lstLogBuffer; std::string m_strFileDir;//文件目录
std::string m_strFileExtendName;//文件扩展名
std::string m_strFileNameFormat;//文件名格式 std::size_t m_nMaxFileSize;//最大文件大小(字节)
std::size_t m_nMaxWriteFileSize;//最大写入文件大小(字节)
mutable std::size_t m_nFileIndex;//文件索引
std::size_t m_nFileCount;//文件最大个数
//线程互斥锁
mutable TinyLogHelper::CLock m_lock; LogLevel m_emLogLevel;//日志等级 std::size_t m_nLogBufferLength;//日志缓存长度(字节)
}; template<>
class CTinyLogM<wchar_t>
{ };
} #endif
TinyLog.cpp文件
#include <time.h>
#include "TinyLog.h" namespace TinyLogHelper
{
#ifdef _WINDOWS //////////////////////////////////////////////////////////////////////////
// 函数功能:
// 获取当前目录
//////////////////////////////////////////////////////////////////////////
template<>
std::string GetCurrentDir<std::string>()
{
std::string s(256, '\0');
DWORD dwLength = GetCurrentDirectoryA(s.size(), &s[0]);
return s.substr(0, dwLength);
} template<>
std::wstring GetCurrentDir<std::wstring>()
{
std::wstring s(256, L'\0');
DWORD dwLength = GetCurrentDirectoryW(s.size(), &s[0]);
return s.substr(0, dwLength);
}
#endif
} namespace TinyLog
{
CTinyLog<char>::CTinyLog()
{
m_strFileDir = TinyLogHelper::GetCurrentDir<std::string>();
m_strFileDir += "/";
SetFillExtendName(".log");
SetFileNameFormat("_%d"); SetMaxFileSize(1 * 1024 * 1024);//1 MB
SetMaxWriteFileSize(4 * 1024);//4 KB
SetMaxFileCount(10);
m_nFileIndex = 1;
m_emLogLevel = LogLevelInfo;
m_nLogBufferLength = 0;
} CTinyLog<char>::~CTinyLog()
{
WriteToFile();
} //添加日志记录
CTinyLog<char>& CTinyLog<char>::operator <<(const char* pszMessage)
{
time_t timet;
struct tm* pTime = NULL;
char szTime[256] = {0};
int nCharNum = 0;
//得到当前时间
time(&timet);
pTime = localtime(&timet);
nCharNum = sprintf(szTime, "%02d-%02d-%02d\t", pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
if (nCharNum > 0)
{
std::string s;
s = s + szTime + pszMessage;
m_lstLogBuffer.push_back(s);//添加记录
m_nLogBufferLength += (s.size() + 2);
}
//写入缓存日志到文件
if (m_nLogBufferLength > m_nMaxWriteFileSize)
{
WriteToFile();
} return *this;
} //添加调试日志
void CTinyLog<char>::Debug(const char* pszMessage)
{
if (m_emLogLevel == LogLevelDebug)
{
std::string s = pszLogLevelString[m_emLogLevel];
s = s + "\t" + pszMessage;
*this << s.c_str();
}
} //添加信息日志
void CTinyLog<char>::Info(const char* pszMessage)
{
if (m_emLogLevel == LogLevelInfo ||
m_emLogLevel == LogLevelDebug)
{
std::string s = pszLogLevelString[m_emLogLevel];
s = s + "\t" + pszMessage;
*this << s.c_str();
}
} //添加错误日志
void CTinyLog<char>::Error(const char* pszMessage)
{
if (m_emLogLevel == LogLevelError ||
m_emLogLevel == LogLevelDebug)
{
std::string s = pszLogLevelString[m_emLogLevel];
s = s + "\t" + pszMessage;
*this << s.c_str();
}
} //将日志缓存写入到文件中
CTinyLog<char>& CTinyLog<char>::WriteToFile()
{
bool bRet = false; try
{
std::string path;
std::ofstream ofs;
//打开第一个写入的文件
path = GetFirstWriteFilePath();
if (path.empty())
{
bRet = false;
throw bRet;
}
ofs.open(path, std::ios::app);
if (!ofs.is_open())
{
bRet = false;
throw bRet;
}
std::size_t nFileSize = 0;
std::list<std::string>::iterator beg, end; beg = m_lstLogBuffer.begin();
end = m_lstLogBuffer.end();
while (beg != end)
{
ofs.seekp(0, std::ios::end);
nFileSize = ofs.tellp();
if (nFileSize + beg->size() + 2 < m_nMaxFileSize)
{
ofs << *beg << std::endl;//回车换行
m_nLogBufferLength -= (beg->size() + 2);
beg = m_lstLogBuffer.erase(beg);
}
else
{
//打开下一个写入的文件
path = GetNextWriteFilePath();
if (path.empty())
{
bRet = false;
throw bRet;
}
if (ofs.is_open())
{
ofs.close();
}
ofs.open(path, std::ios::app);
if (!ofs.is_open())
{
bRet = false;
throw bRet;
}
}
}
bRet = true;
}
catch (bool)
{
} return *this;
} //得到第一个写入文件路径
std::string CTinyLog<char>::GetFirstWriteFilePath() const
{
std::string path; try
{
std::string strPathFromat = GetCurrentFilePathFormat();
std::size_t nPos = strPathFromat.rfind("%d");
if (nPos == strPathFromat.npos)
{
path = "";
throw path;
} std::string strTempPath;
char szNumber[32] = {0};
std::ifstream file; for (std::size_t i = m_nFileIndex; i < m_nFileCount + 1; ++i)
{
memset(szNumber, 0, 32);
itoa(i, szNumber, 10);
strTempPath = strPathFromat;
strTempPath.replace(nPos, 2, szNumber); file.open(strTempPath, std::ios::app);
if (file.is_open())
{
file.seekg(0, std::ios::end);
if (file.tellg() < m_nMaxFileSize)
{
m_nFileIndex = i;
path = strTempPath;
break;
}
}
else
{
m_nFileIndex = i;
path = strTempPath;
break;
}
}
}
catch (const std::string&)
{
} return path;
} //得到下一个写入文件路径
std::string CTinyLog<char>::GetNextWriteFilePath() const
{
std::string path;
std::string strFilePathFormat;
std::size_t nPos = 0;
char szNum[32] = {0}; if (m_nFileIndex > m_nFileCount-1)
{
return path;
}
strFilePathFormat = GetCurrentFilePathFormat();
nPos = strFilePathFormat.rfind("%d");
if (nPos != strFilePathFormat.npos)
{
++m_nFileIndex;
itoa(m_nFileIndex, szNum, 10);
path = strFilePathFormat;
path.replace(nPos, 2, szNum);
}
return path;
} //得到文件路径格式
std::string CTinyLog<char>::GetCurrentFilePathFormat() const
{
//文件路径格式
std::string strFilePathFormat; try
{
if (m_strFileDir.empty() ||
m_strFileNameFormat.empty() ||
m_strFileExtendName.empty())
{
strFilePathFormat = "";
throw strFilePathFormat;
}
//获取本地时间
time_t timet;
struct tm* pTime = NULL;
char szTime[256] = {0}; time(&timet);
pTime = localtime(&timet);
sprintf(szTime, "%d-%02d-%02d", 1900 + pTime->tm_year, 1 + pTime->tm_mon, pTime->tm_mday);
strFilePathFormat = m_strFileDir + szTime + m_strFileNameFormat + m_strFileExtendName;
}
catch (const std::string&)
{
} return strFilePathFormat;
} //设置文件目录
bool CTinyLog<char>::SetFileDir(const std::string& strFileDir)
{
if (!strFileDir.empty() &&
(strFileDir.back() == '\\' ||
strFileDir.back() == '/'))
{
m_strFileDir = strFileDir;
return true;
}
return false;
} //设置文件扩展名
bool CTinyLog<char>::SetFillExtendName(const std::string& strFileExtendName)
{
if (strFileExtendName.size() > 1 &&
strFileExtendName.front() == '.')
{
m_strFileExtendName = strFileExtendName;
return true;
}
return false;
} //设置文件名称格式
bool CTinyLog<char>::SetFileNameFormat(const std::string& strFileNameFormat)
{
if (strFileNameFormat.size() > 1 &&
strFileNameFormat.find("%d") != strFileNameFormat.npos)
{
m_strFileNameFormat = strFileNameFormat;
return true;
}
return false;
} //设置最大文件大小(字节)
void CTinyLog<char>::SetMaxFileSize(std::size_t size)
{
m_nMaxFileSize = size;
} //设置最大写入文件大小(字节)
void CTinyLog<char>::SetMaxWriteFileSize(std::size_t size)
{
m_nMaxWriteFileSize = size;
} //设置最大文件个数
void CTinyLog<char>::SetMaxFileCount(std::size_t count)
{
m_nFileCount = count;
} //设置日志等级
void CTinyLog<char>::SetLogLevel(LogLevel emLogLevel)
{
m_emLogLevel = emLogLevel;
} //////////////////////////////////////////////////////////////////////////
// 类说明:
// 多线程日志类,可以在多个线程中操作日志
//////////////////////////////////////////////////////////////////////////
CTinyLogM<char>::CTinyLogM()
{
m_strFileDir = TinyLogHelper::GetCurrentDir<std::string>();
m_strFileDir += "/";
SetFillExtendName(".log");
SetFileNameFormat("_%d"); SetMaxFileSize(1 * 1024 * 1024);//1 MB
SetMaxWriteFileSize(4 * 1024);//4 KB
SetMaxFileCount(10);
m_nFileIndex = 1;
m_emLogLevel = LogLevelInfo;
m_nLogBufferLength = 0;
} CTinyLogM<char>::~CTinyLogM()
{
WriteToFile();
} //添加日志记录
CTinyLogM<char>& CTinyLogM<char>::operator <<(const char* pszMessage)
{
time_t timet;
struct tm* pTime = NULL;
char szTime[256] = {0};
int nCharNum = 0; time(&timet);
pTime = localtime(&timet);
nCharNum = sprintf(szTime, "%02d-%02d-%02d\t", pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
if (nCharNum > 0)
{
std::string s;
s = s + szTime + pszMessage;
m_lock.Lock();
m_lstLogBuffer.push_back(s);
m_nLogBufferLength += (s.size() + 2);
m_lock.UnLock();
} if (m_nLogBufferLength > m_nMaxWriteFileSize)
{
WriteToFile();
} return *this;
} //添加调试日志
void CTinyLogM<char>::Debug(const char* pszMessage)
{
if (m_emLogLevel == LogLevelDebug)
{
*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
}
} //添加信息日志
void CTinyLogM<char>::Info(const char* pszMessage)
{
if (m_emLogLevel == LogLevelInfo ||
m_emLogLevel == LogLevelDebug)
{
*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
}
} //添加错误日志
void CTinyLogM<char>::Error(const char* pszMessage)
{
if (m_emLogLevel == LogLevelError ||
m_emLogLevel == LogLevelDebug)
{
*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
}
} //将日志缓存写入到文件中
CTinyLogM<char>& CTinyLogM<char>::WriteToFile()
{
bool bRet = false; try
{
std::string path;
std::ofstream ofs; //打开第一个写入的文件
path = GetFirstWriteFilePath();
if (path.empty())
{
bRet = false;
throw bRet;
}
m_lock.Lock();
ofs.open(path, std::ios::app);
if (!ofs.is_open())
{
bRet = false;
throw bRet;
}
std::size_t nFileSize = 0;
std::list<std::string>::iterator beg, end; beg = m_lstLogBuffer.begin();
end = m_lstLogBuffer.end();
while (beg != end)
{
ofs.seekp(0, std::ios::end);
nFileSize = ofs.tellp();
if (nFileSize + beg->size() + 2 < m_nMaxFileSize)
{
ofs << *beg << std::endl;//回车换行
m_nLogBufferLength -= (beg->size() + 2);
beg = m_lstLogBuffer.erase(beg);
}
else
{
//打开下一个写入的文件
path = GetNextWriteFilePath();
if (path.empty())
{
bRet = false;
throw bRet;
}
if (ofs.is_open())
{
ofs.close();
}
ofs.open(path, std::ios::app);
if (!ofs.is_open())
{
bRet = false;
throw bRet;
}
}
}
bRet = true;
}
catch (bool)
{
} m_lock.UnLock();
return *this;
} //得到第一个写入文件路径
std::string CTinyLogM<char>::GetFirstWriteFilePath() const
{
std::string path; try
{
std::string strPathFromat = GetCurrentFilePathFormat();
std::size_t nPos = strPathFromat.rfind("%d");
if (nPos == strPathFromat.npos)
{
path = "";
throw path;
} std::string strTempPath;
char szNumber[32] = {0};
std::ifstream file; m_lock.Lock();
for (std::size_t i = m_nFileIndex; i < m_nFileCount + 1; ++i)
{
memset(szNumber, 0, 32);
itoa(i, szNumber, 10);
strTempPath = strPathFromat;
strTempPath.replace(nPos, 2, szNumber); file.open(strTempPath, std::ios::app);
if (file.is_open())
{
file.seekg(0, std::ios::end);
if (file.tellg() < m_nMaxFileSize)
{
m_nFileIndex = i;
path = strTempPath;
break;
}
}
else
{
m_nFileIndex = i;
path = strTempPath;
break;
}
}
m_lock.UnLock();
}
catch (const std::string&)
{
} return path;
} //得到下一个写入文件路径
std::string CTinyLogM<char>::GetNextWriteFilePath() const
{
std::string path;
std::string strFilePathFormat;
std::size_t nPos = 0;
char szNum[32] = {0}; if (m_nFileIndex > m_nFileCount-1)
{
return path;
}
strFilePathFormat = GetCurrentFilePathFormat();
nPos = strFilePathFormat.rfind("%d");
if (nPos != strFilePathFormat.npos)
{
m_lock.Lock();
++m_nFileIndex;
m_lock.UnLock();
itoa(m_nFileIndex, szNum, 10);
path = strFilePathFormat;
path.replace(nPos, 2, szNum);
}
return path;
} //得到文件路径格式
std::string CTinyLogM<char>::GetCurrentFilePathFormat() const
{
//文件路径格式
std::string strFilePathFormat; try
{
if (m_strFileDir.empty() ||
m_strFileNameFormat.empty() ||
m_strFileExtendName.empty())
{
strFilePathFormat = "";
throw strFilePathFormat;
}
//获取本地时间
time_t timet;
struct tm* pTime = NULL;
char szTime[256] = {0}; time(&timet);
pTime = localtime(&timet);
sprintf(szTime, "%d-%02d-%02d", 1900 + pTime->tm_year, 1 + pTime->tm_mon, pTime->tm_mday);
strFilePathFormat = m_strFileDir + szTime + m_strFileNameFormat + m_strFileExtendName;
}
catch (const std::string&)
{
} return strFilePathFormat;
} //设置文件目录
bool CTinyLogM<char>::SetFileDir(const std::string& strFileDir)
{
if (!strFileDir.empty() &&
(strFileDir.back() == '\\' ||
strFileDir.back() == '/'))
{
m_lock.Lock();
m_strFileDir = strFileDir;
m_lock.UnLock();
return true;
}
return false;
} //设置文件扩展名
bool CTinyLogM<char>::SetFillExtendName(const std::string& strFileExtendName)
{
if (strFileExtendName.size() > 1 &&
strFileExtendName.front() == '.')
{
m_lock.Lock();
m_strFileExtendName = strFileExtendName;
m_lock.UnLock();
return true;
}
return false;
} //设置文件名称格式
bool CTinyLogM<char>::SetFileNameFormat(const std::string& strFileNameFormat)
{
if (strFileNameFormat.size() > 1 &&
strFileNameFormat.find("%d") != strFileNameFormat.npos)
{
m_lock.Lock();
m_strFileNameFormat = strFileNameFormat;
m_lock.UnLock();
return true;
}
return false;
} //设置最大文件大小(字节)
void CTinyLogM<char>::SetMaxFileSize(std::size_t size)
{
m_lock.Lock();
m_nMaxFileSize = size;
m_lock.UnLock();
} //设置最大写入文件大小(字节)
void CTinyLogM<char>::SetMaxWriteFileSize(std::size_t size)
{
m_lock.Lock();
m_nMaxWriteFileSize = size;
m_lock.UnLock();
} //设置最大文件个数
void CTinyLogM<char>::SetMaxFileCount(std::size_t count)
{
m_nFileCount = count;
} //设置日志等级
void CTinyLogM<char>::SetLogLevel(LogLevel emLogLevel)
{
m_emLogLevel = emLogLevel;
}
}
测试:
TinyLog::CTinyLog<char> log; log.SetMaxFileSize(1 * 1024 * 1024);
log.SetMaxWriteFileSize(1 * 1024 * 1024);
log.SetLogLevel(TinyLog::LogLevelError);
for (int i = 0; i < 60000; ++i)
{
log.Error("Hello Word!");
}
log.WriteToFile();
c++ 日志操作的更多相关文章
- mysql 查看 删除 日志操作总结(包括单独和主从mysql)
我们可以在mysql的安装目录下看到mysql的二进制日志文件,如mysql-bin.000***等,很多人都不及时的处理,导致整个硬盘被塞满也是有可能的.这些是数据库的操作日志.它记录了我们平时使用 ...
- SQL Server 最小化日志操作解析,应用
Sql Server 中数据库在BULK_LOGGED/SIMPLE模式下的一些操作会采用最小化日志的记录方式,以减小tran log落盘日志量从而提高整体性能. 这里我简单介绍下哪些操作在什么样的情 ...
- 使用Log4j进行日志操作
使用Log4j进行日志操作 一.Log4j简介 (1)概述 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接字服 ...
- SQL Server 最小化日志操作解析,应用[手稿]
Sql Server 中数据库在BULK_LOGGED/SIMPLE模式下的一些操作会采用最小化日志的记录方式,以减小tran log落盘日志量从而提高整体性能. 这里我简单介绍下哪些操作在什么样的情 ...
- xBIM 日志操作
目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...
- python中的日志操作和发送邮件
1.python中的日志操作 安装log模块:pip install nnlog 参数:my_log = nnlog.Logger('server_log.log',level='debug',bac ...
- 从零开始的Python学习Episode 14——日志操作
日志操作 一.logging模块 %(message)s 日志信息 %(levelno)s 日志级别 datefmt 设置时间格式 filename 设置日志保存的路径 level 设置日志记录的级别 ...
- Java 使用Log4J进行日志操作
使用Log4J进行日志操作 Log4J简介 Log4J是Apache的一个开放源代码项目,它是一个日志操作包,通过使用Log4J,可以指定日志信息输出的目的地,如控制台.文件.CUI组件.NT ...
- Python之日志操作(logging)
import logging 1.自定义日志级别,日志格式,输出位置 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s | ...
- 2.NetDh框架之简单高效的日志操作类(附源码和示例代码)
前言 NetDh框架适用于C/S.B/S的服务端框架,可用于项目开发和学习.目前包含以下四个模块 1.数据库操作层封装Dapper,支持多种数据库类型.多库实例,简单强大: 此部分具体说明可参考博客: ...
随机推荐
- deepin2014.1快捷键
初试deepin2014.1,发现windows很多快捷键在deepin中也完美支持,举例如下: ctrl+shift+n : 新建文件夹 窗口键+E:打开文件系统 窗口键+TAB:3D切换桌面 al ...
- Django中使用ModelForm实现Admin功能
接上一篇<Django中使用Bootstrap> ModelForm 可以将数据库中的信息展示在一个表中,因此我们在查询数据库信息时可以使用ModelForm在前端展示查询到的信息. 在上 ...
- chapter 13_1 算术类的元方法
假设用table来表示集合,用function去计算集合的交集.并集. 为了保持名称空间的整齐,将这些函数存入一个名为Set的table中. 现在,假设用“+”来计算两个集合的并集,那么就要让所有用于 ...
- UI弹出键盘和收回键盘
点击textfield,会自动弹出键盘 要让键盘收回来,先设置个代理:[field setTextFieldDelegate:self]; 可设置成自己,也可设置成其他对象,只要在对应的类中,遵循U ...
- HTML URL编码参考(转载)
URL编码(URL encoding)的作用是将字符转化为可在因特网上安全传输的格式.URL——统一资源定位符Web浏览器通过URL从Web服务器上请求页面.URL就是网页的地址,如:http://w ...
- CentOS 7 安装Python pip
1 首先安装epel扩展源: sudo yum -y install epel-release 2 然后安装python-pip sudo yum -y install python-pip 3安装完 ...
- 【CRC校验】学习笔记
#include<stdio.h> unsigned ]= { 0x01,0x02,0x03,0x04,0x05,0x06 }; ] = { 0x0000, 0x1021, 0x2042, ...
- win7 xp 双系统安装记录
原机win7 64 增加xp x86 win7在c盘,xp装h盘 1.老毛桃pe,雨林木风gho,蓝屏,0000007b 2.通用pe.雨林木风gho,蓝屏,00000007b 3.pe设置h盘为系统 ...
- gridControl 中CellValueChanged,ShowingEditor,CustomDrawCell的用法
private void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventA ...
- Struts2--课程笔记3
获取ServletAPI: 第一种方式: //在request域中放入属性req,暂且认为getContext()获取的是request域空间,但实际不是 ActionContext.g ...