zoukankan      html  css  js  c++  java
  • Delphi 写日志的类

    unit uProgLog;
    
    interface
    
    uses
    Windows, SysUtils, SyncObjs;
    
    const
    C_LOG_LEVEL_TRACE   = $00000001;
    C_LOG_LEVEL_WARNING = $00000002;
    C_LOG_LEVEL_ERROR   = $00000004;
    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 := 31;
    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 = 0) then exit;
    
    FileMask := FLogPath + FLogAppName + '*.log';
    bResult := FindFirst(FileMask, faAnyFile, SearchRec) = 0;
    try
        if bResult then
        begin
          repeat
            if (SearchRec.Name[1] <> '.') 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) <> 0;
        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
          // 1. close the current log file?
          if (FLogOpened and
              (currentTimeStamp.Date <> FFileTimeStamp.Date)) then
          begin
            CloseFile(FLogFile);
            FLogOpened := False;
          end;
    
          // 2. 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, ' ', '0', [rfReplaceAll]);
    
            fileName := Format('%s%s%s.log', [FLogPath, FLogAppName, szDate]);
    
            Assignfile(FLogFile, fileName);
            //if FileExists(fileName) then append(FLogFile)
            //else rewrite(FLogFile);
    
            //$1 modify by zhajl 2005-11-30
            // 如果无法打开日志文件,则退出
            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;
    
          // 3. 写日志内容
          ASSERT(FLogOpened);
          if (FLogOpened) then
          begin
            szDate := Format('%4d/%2d/%2d',
                  [currentSQLTimeStamp.Year, currentSQLTimeStamp.Month, currentSQLTimeStamp.Day]);
            // Format函数不支持在宽度不足位添0,只好用replace添加
            szDate := StringReplace(szDate, ' ', '0', [rfReplaceAll]);
            szTime := Format('%2d:%2d:%2d',
                  [currentSQLTimeStamp.Hour, currentSQLTimeStamp.Minute, currentSQLTimeStamp.Second]);
            szTime := StringReplace(szTime, ' ', '0', [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.
    View Code
  • 相关阅读:
    /usr/bin/ld: 找不到 /usr/lib64/libatomic.so.1.0.0
    linux Version mismatch error. This is libtool 2.4.6 Debian-2.4.6-2
    java播放语音文件
    java冒泡排序
    java递归求和
    常见芯片标号说明
    keil5 新建 stm32项目 步骤
    st-link 升级固件时报错“is not in the DFU mode”
    数码管 段选位选
    C51 定时器
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/3289269.html
Copyright © 2011-2022 走看看