程序需要一个简单的日志类,为此简单学习了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++ 日志操作的更多相关文章

  1. mysql 查看 删除 日志操作总结(包括单独和主从mysql)

    我们可以在mysql的安装目录下看到mysql的二进制日志文件,如mysql-bin.000***等,很多人都不及时的处理,导致整个硬盘被塞满也是有可能的.这些是数据库的操作日志.它记录了我们平时使用 ...

  2. SQL Server 最小化日志操作解析,应用

    Sql Server 中数据库在BULK_LOGGED/SIMPLE模式下的一些操作会采用最小化日志的记录方式,以减小tran log落盘日志量从而提高整体性能. 这里我简单介绍下哪些操作在什么样的情 ...

  3. 使用Log4j进行日志操作

    使用Log4j进行日志操作 一.Log4j简介 (1)概述 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接字服 ...

  4. SQL Server 最小化日志操作解析,应用[手稿]

    Sql Server 中数据库在BULK_LOGGED/SIMPLE模式下的一些操作会采用最小化日志的记录方式,以减小tran log落盘日志量从而提高整体性能. 这里我简单介绍下哪些操作在什么样的情 ...

  5. xBIM 日志操作

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  6. python中的日志操作和发送邮件

    1.python中的日志操作 安装log模块:pip install nnlog 参数:my_log = nnlog.Logger('server_log.log',level='debug',bac ...

  7. 从零开始的Python学习Episode 14——日志操作

    日志操作 一.logging模块 %(message)s 日志信息 %(levelno)s 日志级别 datefmt 设置时间格式 filename 设置日志保存的路径 level 设置日志记录的级别 ...

  8. Java 使用Log4J进行日志操作

    使用Log4J进行日志操作   Log4J简介   Log4J是Apache的一个开放源代码项目,它是一个日志操作包,通过使用Log4J,可以指定日志信息输出的目的地,如控制台.文件.CUI组件.NT ...

  9. Python之日志操作(logging)

    import logging   1.自定义日志级别,日志格式,输出位置 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s | ...

  10. 2.NetDh框架之简单高效的日志操作类(附源码和示例代码)

    前言 NetDh框架适用于C/S.B/S的服务端框架,可用于项目开发和学习.目前包含以下四个模块 1.数据库操作层封装Dapper,支持多种数据库类型.多库实例,简单强大: 此部分具体说明可参考博客: ...

随机推荐

  1. Union、Union All、Except、InterSect的区别

    UNION: 将多个「结果集 (result set)」的「行 (row)」合并,作为单个结果集返回,并移除重复的行.若有重复的行,只留下一个. UNION ALL: 将多个「结果集 (result ...

  2. infix to postfix 完整版

    #include<iostream> #include<stack> #include<string> #include<deque> using na ...

  3. lua的string库

    lua支持的所有字符类 .      任意字符 %a   字母 %c 控制字符 %d 数字 %l         小写字母 %p  标点字符 %s 空白符 %u        大写字母 %w   字母 ...

  4. PHP ajax 限制 API 来源限制

    if(isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_RE ...

  5. C# using

    我们知道 using 语句只不过是提供能确保正确使用 IDisposable 对象的方便语法. 1: using (IDisposable reader1 = new StreamReader(inp ...

  6. 第三次冲刺spring会议(第五次会议)

    [例会时间]2014/5/24 21:15 [例会地点]9#446 [例会形式]轮流发言 [例会主持]马翔 [例会记录]兰梦 小组成员:兰梦 ,马翔,李金吉,赵天,胡佳奇

  7. HttpClient模拟get,post请求并发送请求参数(json等)

    import java.io.IOException; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org. ...

  8. linux双线ip设置(不需额外增加路由表)

    linux 双线ip设置(不需额外增加路由表,只需修改下面就ok了)修改   vi /etc/iproute2/rt_tables              (增加电信和网通两个路由表) 增加252  ...

  9. ajax 假上传文件

    1. <form name="certForm" id="certForm" method="post" action="x ...

  10. strace -o /tmp/dhc$$ dhclient -d eth2

    http://askubuntu.com/questions/5187/why-is-dhclient-saying-siocsifaddr-permission-denied ip link add ...