Delphi 写日志的类
unit uProgLog; interface uses
Windows, SysUtils, SyncObjs; const
C_LOG_LEVEL_TRACE = $;
C_LOG_LEVEL_WARNING = $;
C_LOG_LEVEL_ERROR = $;
type
EnumSeverity = (TraceLevel, WarningLevel, ErrorLevel, LogLevel); function SeverityDesc(severity: EnumSeverity): string; type
TLogFile = class
private
FLogKeepDays: Integer; //日志保存时间
FLogLevel: DWORD; //日志级别
FLogPath: string; //日志保存路径,以"\"结尾
FLogAppName: string; //应用程序名(日志文件前缀) FCsWriteLogFile: TCriticalSection;
FLogFile: TextFile; //日志文件句柄
FLogOpened: Boolean; //日志文件是否打开
FFileTimeStamp: TTimeStamp; //当前日志文件创建或打开时间 function GetLogKeepDays(): Integer;
procedure SetLogKeepDays(days: Integer);
function GetLogLevel(): DWORD;
procedure SetLogLevel(level: DWORD);
function GetLogPath(): string;
procedure SetLogPath(path: string);
function GetLogAppName(): string;
procedure SetLogAppName(name: string);
protected
function WriteLogFile(const szFormat: string; const Args: array of const): Boolean;
public ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: Trace()
//Describe: 记录日志到日志文件。如果日志文件路径不存在,会自动创建。如果日志文件不存在,
// 则创建相应的日志文件;如果日子文件已存在,则打开相应的日志文件,并将日志添加到文件结尾。
//Input : severity: 日志级别。根据日志级别参数决定该级别日志是否需要保存,
// 但LogLevel级别的日志不受日志级别参数影响,都保存到了日志文件。
// subject: 模块名称。
// desc: 日志内容。
//Result : N/A
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
procedure Trace(severity: EnumSeverity; const subject, desc: string); overload; ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: Trace()
//Describe: 记录日志到日志文件。如果日志文件路径不存在,会自动创建。如果日志文件不存在,
// 则创建相应的日志文件;如果日子文件已存在,则打开相应的日志文件,并将日志添加到文件结尾。
//Input : severity: 日志级别。根据日志级别参数决定该级别日志是否需要保存,
// 但LogLevel级别的日志不受日志级别参数影响,都保存到了日志文件。
// subject: 模块名称。
// descFormat: 包含格式化信息的日志内容。
// Args: 格式化参数数组。
//Result : N/A
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
procedure Trace(severity: EnumSeverity; const subject, descFormat: string; const Args: array of const); overload; ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: DeleteLogFile()
//Describe: 删除超过保存期限的日志文件。在日志文件路径中搜索超过保存期限的日志,将之删除。
// 该方法只需在应用程序启动时调用一次,以删除超过保存期限的日志。
//Input : N/A
//Result : Boolean 成功返回TRUE,失败返回FALSE
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
function DeleteLogFile(): Boolean; constructor Create();
Destructor Destroy(); override; property LogKeepDays: Integer read GetLogKeepDays write SetLogKeepDays;
property Level: DWORD read GetLogLevel write SetLogLevel;
property LogPath: string read GetLogPath write SetLogPath;
property LogAppName: string read GetLogAppName write SetLogAppName;
end; function BooleanDesc(Value : Boolean): string; implementation uses Forms, SqlTimSt; function BooleanDesc(Value : Boolean): string;
begin
if Value then Result := 'TRUE'
else Result := 'FALSE';
end; function SeverityDesc(severity: EnumSeverity): string;
begin
if (severity = ErrorLevel) then result := 'X'
else if (severity = WarningLevel) then result := '!'
else result := ' ';
end; { TLogFile } constructor TLogFile.Create;
begin
FLogOpened := False;
FCsWriteLogFile := TCriticalSection.Create; FLogKeepDays := ;
FLogLevel := C_LOG_LEVEL_TRACE or C_LOG_LEVEL_WARNING or C_LOG_LEVEL_ERROR;
FLogPath := ExtractFilePath(Application.ExeName) + 'Log\';
FLogAppName := ChangeFileExt(ExtractFileName(Application.ExeName),'');
end; function TLogFile.DeleteLogFile(): Boolean;
var
rc : DWORD;
SearchRec: TSearchRec;
bResult: Boolean;
FileMask: string;
LocalFileTime: TFileTime;
FileTime: Integer;
begin
result := false;
rc := GetFileAttributes(PChar(FLogPath));
if (rc = $FFFFFFFF) or (FILE_ATTRIBUTE_DIRECTORY and rc = ) then exit; FileMask := FLogPath + FLogAppName + '*.log';
bResult := FindFirst(FileMask, faAnyFile, SearchRec) = ;
try
if bResult then
begin
repeat
if (SearchRec.Name[] <> '.') and
(SearchRec.Attr and faVolumeID <> faVolumeID) and
(SearchRec.Attr and faDirectory <> faDirectory) then
begin
FileTimeToLocalFileTime(SearchRec.FindData.ftCreationTime, LocalFileTime);
FileTimeToDosDateTime(LocalFileTime, LongRec(FileTime).Hi, LongRec(FileTime).Lo);
// 按照文件创建日期删除文件
if FileDateToDateTime(FileTime) <= Now() - GetLogKeepDays() then
DeleteFile(FLogPath + SearchRec.Name);
end;
until FindNext(SearchRec) <> ;
end;
finally
FindClose(SearchRec);
end;
end; destructor TLogFile.Destroy;
begin
if (FLogOpened) then CloseFile(FLogFile);
FCsWriteLogFile.Free();
inherited;
end; function TLogFile.GetLogAppName: string;
begin
result := FLogAppName;
end; function TLogFile.GetLogKeepDays: Integer;
begin
result := FLogKeepDays;
end; function TLogFile.GetLogLevel: DWORD;
begin
result := FLogLevel;
end; function TLogFile.GetLogPath: string;
begin
result := FLogPath;
end; procedure TLogFile.SetLogAppName(name: string);
begin
FLogAppName := ChangeFileExt(name, '');
end; procedure TLogFile.SetLogKeepDays(days: Integer);
begin
FLogKeepDays := days;
end; procedure TLogFile.SetLogLevel(level: DWORD);
begin
FLogLevel := level;
end; procedure TLogFile.SetLogPath(path: string);
begin
if Trim(path) = '' then exit;
if path[Length(path)] <> '\' then FLogPath := path + '\'
else FLogPath := path;
end; procedure TLogFile.Trace(severity: EnumSeverity; const subject, desc: string);
begin
// 根据配置的日志级别决定是否写日志
if ((severity = LogLevel) or
((severity = ErrorLevel) and (FLogLevel and C_LOG_LEVEL_ERROR = C_LOG_LEVEL_ERROR)) or
((severity = WarningLevel) and (FLogLevel and C_LOG_LEVEL_WARNING = C_LOG_LEVEL_WARNING)) or
((severity = TraceLevel) and (FLogLevel and C_LOG_LEVEL_TRACE = C_LOG_LEVEL_TRACE))) then
begin
WriteLogFile('%s @@ %s @ %s $ %s', [SeverityDesc(severity), FLogAppName, subject, desc]);
end;
end; procedure TLogFile.Trace(severity: EnumSeverity; const subject,
descFormat: string; const Args: array of const);
var
desc: string;
begin
// 根据配置的日志级别决定是否写日志
if ((severity = LogLevel) or
((severity = ErrorLevel) and (FLogLevel and C_LOG_LEVEL_ERROR = C_LOG_LEVEL_ERROR)) or
((severity = WarningLevel) and (FLogLevel and C_LOG_LEVEL_WARNING = C_LOG_LEVEL_WARNING)) or
((severity = TraceLevel) and (FLogLevel and C_LOG_LEVEL_TRACE = C_LOG_LEVEL_TRACE))) then
begin
desc := Format(descFormat, Args);
WriteLogFile('%s @@ %s @ %s $ %s', [SeverityDesc(severity), FLogAppName, subject, desc]);
end;
end; function TLogFile.WriteLogFile(const szFormat: string;
const Args: array of const): Boolean;
var
fileName: string;
currentTime: TDateTime;
currentTimeStamp: TTimeStamp;
currentSQLTimeStamp: TSQLTimeStamp;
buffer: string;
szDate, szTime: string;
begin
result := false; //进入临界区,保证多线程环境下此函数能安全执行
FCsWriteLogFile.Enter();
try
currentTime := Now(); //注意这里得到的是local time
currentSQLTimeStamp := DateTimeToSQLTimeStamp(currentTime);
currentTimeStamp := DateTimeToTimeStamp(currentTime); try
// . close the current log file?
if (FLogOpened and
(currentTimeStamp.Date <> FFileTimeStamp.Date)) then
begin
CloseFile(FLogFile);
FLogOpened := False;
end; // . whether to open a new log file?
if (not FLogOpened) then
begin
// 2.1如果指定的日志目录不存在,则创建它
if not DirectoryExists(FLogPath) then
if not ForceDirectories(FLogPath) then exit; // 2.2 然后再打开当前日志文件
szDate := Format('%4d%2d%2d',
[currentSQLTimeStamp.Year, currentSQLTimeStamp.Month, currentSQLTimeStamp.Day]);
// Format函数不支持在宽度不足位添0,只好用replace添加
szDate := StringReplace(szDate, ' ', '', [rfReplaceAll]); fileName := Format('%s%s%s.log', [FLogPath, FLogAppName, szDate]); Assignfile(FLogFile, fileName);
//if FileExists(fileName) then append(FLogFile)
//else rewrite(FLogFile); //$ modify by zhajl --
// 如果无法打开日志文件,则退出
try
if FileExists(fileName) then append(FLogFile)
else rewrite(FLogFile);
FLogOpened := True;
except
// 如果无法打开日志文件
FLogOpened := False;
//这里用CloseFile会出现异常
//CloseFile(FLogFile);
exit;
end; // 更新文件创建时间。要注意这里是 local time
FFileTimeStamp := DateTimeToTimeStamp(currentTime);
end; // . 写日志内容
ASSERT(FLogOpened);
if (FLogOpened) then
begin
szDate := Format('%4d/%2d/%2d',
[currentSQLTimeStamp.Year, currentSQLTimeStamp.Month, currentSQLTimeStamp.Day]);
// Format函数不支持在宽度不足位添0,只好用replace添加
szDate := StringReplace(szDate, ' ', '', [rfReplaceAll]);
szTime := Format('%2d:%2d:%2d',
[currentSQLTimeStamp.Hour, currentSQLTimeStamp.Minute, currentSQLTimeStamp.Second]);
szTime := StringReplace(szTime, ' ', '', [rfReplaceAll]); buffer := Format('%s %s ', [szDate, szTime]); // '%4d/%2d/%2d %2d:%2d:%2d '
buffer := buffer + szFormat;
buffer := Format(buffer, Args); writeln(FLogFile, buffer);
Flush(FLogFile); // 是否考虑性能而注释之?
end;
except
//写日志文件操作中若有异常(如目录是只读的等),则忽略它
end;
finally
FCsWriteLogFile.Leave; //离开临界区
end;
result := true;
end; end.
Delphi 写日志的类的更多相关文章
- C#写日志工具类
代码: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System ...
- 2.2 代码块--delphi 写日志模块
//2.2 代码块--写日志 //调用例句如:LogMsg('FTP上传线程终止',False,true); procedure LogMsg(AMsg: string; const blnIsErr ...
- c# 多线程使用队列顺序写日志的类 (需要再优化)
using System; using System.Collections.Generic; using System.Threading; public class LogManager { // ...
- PHP写日志公共类
Txl_Log.php <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * * * ...
- 写日志(log)
已下为我自己写的一个写日志的类,比较简洁. <?php class Log { /** * @Purpose : 写日志 * @Method Name : writeLog() * @param ...
- C#写文本日志帮助类(支持多线程)改进版(不适用于ASP.NET程序)
由于iis的自动回收机制,不适用于ASP.NET程序 代码: using System; using System.Collections.Concurrent; using System.Confi ...
- C#写文本日志帮助类(支持多线程)
代码: using System; using System.Configuration; using System.IO; using System.Threading.Tasks; namespa ...
- 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)
一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...
- .NET Core的日志[5]:利用TraceSource写日志
从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录.在.NET ...
随机推荐
- Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
上文简介了HttpClient和Tomcatserver的交互,主角是HttpClient,然后它跟server交互有两种方式即get和post.所以这个HttpClient就相似于电脑上用的浏览器. ...
- Windows下配置Nginx使之支持PHP(转)
平台描述:Windows下,使用PHP套件 xampp,因为是测试玩,所以没在服务器 Linux 环境中配置. 1. 首先,将 nginx.conf 中的 PHP 配置注释去掉. 01 # pass ...
- Fedora14下首次搭建Samba服务器遇到的一些问题
SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的通信协议.而Samba则是在Linux和Unix系统上实现SMB协议的一个免费软件,由服务器及客户端程 ...
- [转] HBase的特征和优点
from: http://blog.jobbole.com/83614/ 概念:行键,列簇 Hbase 是运行在Hadoop上的NoSQL数据库,它是一个分布式的和可扩展的大数据仓库,也就是说HBas ...
- 挖掘微信Web版通信的全过程
昨天是周末,在家闲得无聊,于是去weiphone.com逛了一圈,偶然发现有人发了一帖叫<微信 for Mac>,这勾起了我的好奇心,国内做Mac开发的人确实很少,对于那些能够独自开发一些 ...
- TCP/IP协议原理与应用笔记10:TCP/IP协议族
1. 协议族视图如下:(这里我们列举重要的,并不是所有的) (1)网络接入层(数据链路层 和 物理层): 通过接入的物理网络的 功能 和 覆盖范围 进行分析划分为: •LANs :局域网(Local ...
- Android(java)学习笔记231:服务(service)之混合方式开启服务
1. 前面我们已经讲过可以使用两种方式开启服务 startService----stopService: oncreate() ---> onstartCommand() ---& ...
- 使用搬瓦工搭建javaweb环境
/* 本文是基于搬瓦工vps的centos-6-x86_64的Linux系统搭建. 需准备的工具:1.putty(用于连接Linux系统) 2.WinSCP(搬瓦工官方提供的ftp上传下载工 ...
- 9.7noip模拟试题
题目名称 日历游戏 最大公约数 密码 英文代号 calendar gcd pasuwado 输入文件名 calendar.in gcd.in pasuwado.in 输出文件名 calendar.ou ...
- C#中的操作数据库的SQLHelper类
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using ...