c++ 多线程写日志的一个很实用的日志类源码(支持 c++ builder)

简介:

1.日志基类

.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//---------------------------------------------------------------------------
#ifndef UnitLogWriterH
#define UnitLogWriterH
#include <vcl.h>
#include <time.h>
#include <assert.h>
//---------------------------------------------------------------------------
class  LogFile
{
protected :
     CRITICAL_SECTION _csLock;
     char  * _szFileName;
     HANDLE  _hFile;
     bool  OpenFile(); //打开文件, 指针到文件尾
     DWORD  Write( LPCVOID  lpBuffer, DWORD  dwLength);
     virtual  void  WriteLog( LPCVOID  lpBuffer, DWORD  dwLength); //写日志, 可以扩展修改
     void  Lock()   { ::EnterCriticalSection(&_csLock); }
     void  Unlock() { ::LeaveCriticalSection(&_csLock); }
public :
     LogFile( const  char  *szFileName = "Log.log" ); //设定日志文件名
     virtual  ~LogFile();
     const  char  * GetFileName()
     {
        return  _szFileName;
     }
 
     void  SetFileName( const  char  *szName); //修改文件名, 同时关闭上一个日志文件
     bool  IsOpen()
     {
        return  _hFile != INVALID_HANDLE_VALUE;
     }
 
     void  Close();
 
     void  Log( LPCVOID  lpBuffer, DWORD  dwLength); //追加日志内容
 
     void  Log( const  char  *szText)
     {
        Log(szText, strlen (szText));
     }
private : //屏蔽函数
     LogFile( const  LogFile&);
     LogFile&operator = ( const  LogFile&);
};
#endif

 

 

基类cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//---------------------------------------------------------------------------
 
 
#pragma hdrstop
 
#include "UnitLogWriter.h"
 
//---------------------------------------------------------------------------
 
#pragma package(smart_init)
LogFile::LogFile( const  char  *szFileName)
{
    _szFileName = NULL;
    _hFile = INVALID_HANDLE_VALUE;
    ::InitializeCriticalSection(&_csLock);
 
    SetFileName(szFileName);
}
//-------------------------------------------------------------------------
LogFile::~LogFile()
{
     ::DeleteCriticalSection(&_csLock);
     Close();
 
     if (_szFileName)
         delete  []_szFileName;
}
//-------------------------------------------------------------------------
 
bool  LogFile::OpenFile()
{
     if (IsOpen())
         return  true ;
     if (!_szFileName)
         return  false ;
 
     _hFile = CreateFile(
                         _szFileName,
                         GENERIC_WRITE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
 
     if (!IsOpen() && GetLastError() == 2) //打开不成功, 且因为文件不存在, 创建文件
         _hFile = CreateFile(
                              _szFileName,
                              GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              NULL,
                              OPEN_ALWAYS,
                              FILE_ATTRIBUTE_NORMAL,
                              NULL);
 
     if (IsOpen())
         SetFilePointer(_hFile, 0, NULL, FILE_END);
     return  IsOpen();
}
//-------------------------------------------------------------------------
DWORD  LogFile::Write( LPCVOID  lpBuffer, DWORD  dwLength)
{
     DWORD  dwWriteLength = 0;
     if (IsOpen())
         WriteFile(_hFile, lpBuffer, dwLength, &dwWriteLength, NULL);
     return  dwWriteLength;
}
//-------------------------------------------------------------------------
void  LogFile::WriteLog( LPCVOID  lpBuffer, DWORD  dwLength)
{
     time_t  now;
     char  temp[21];
     DWORD  dwWriteLength;
 
     if (IsOpen())
     {
         time (&now);
         strftime (temp, 20, "%Y-%m-%d %H:%M:%S" , localtime (&now));
 
         WriteFile(_hFile, "\xd\xa#-----------------------------" , 32, &dwWriteLength, NULL);
         WriteFile(_hFile, temp, 19, &dwWriteLength, NULL);
         WriteFile(_hFile, "-----------------------------#\xd\xa" , 32, &dwWriteLength, NULL);
         WriteFile(_hFile, lpBuffer, dwLength, &dwWriteLength, NULL);
         WriteFile(_hFile, "\xd\xa" , 2, &dwWriteLength, NULL);
 
         FlushFileBuffers(_hFile);
 
     }
}
//-------------------------------------------------------------------------
 
//-------------------------------------------------------------------------
void  LogFile::SetFileName( const  char  *szName)
{
        assert (szName);
 
        if (_szFileName)
         delete  []_szFileName;
 
        Close();
 
        _szFileName = new  char [ strlen (szName) + 1];
        assert (_szFileName);
        strcpy (_szFileName, szName);
}
//-------------------------------------------------------------------------
void  LogFile::Close()
{
        if (IsOpen())
        {
         CloseHandle(_hFile);
         _hFile = INVALID_HANDLE_VALUE;
        }
}
//-------------------------------------------------------------------------
void  LogFile::Log( LPCVOID  lpBuffer, DWORD  dwLength)
{
        assert (lpBuffer);
        __try
        {
         Lock();
 
         if (!OpenFile())
          return ;
 
         WriteLog(lpBuffer, dwLength);
        }
        __finally
        {
         Unlock();
        }
}
1
  

2.日志派生类

.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//---------------------------------------------------------------------------
 
#ifndef LogFileExH
#define LogFileExH
#include <assert.h>
 
#include "UnitLogWriter.h"
 
//---------------------------------------------------------------------------
class  LogFileEx : public  LogFile
{
protected :
     char  *_szPath;
     char  _szLastDate[9];
     int  _iType;
     void  SetPath( const  char  *szPath);
public :
     enum  LOG_TYPE{YEAR = 0, MONTH = 1, DAY = 2};
     LogFileEx( const  char  *szPath = "." , LOG_TYPE iType = MONTH);
     ~LogFileEx();
     const  char  * GetPath();
     void  Log( LPCVOID  lpBuffer, DWORD  dwLength);
     void  Log( const  char  *szText);
     void  Log( const  AnsiString&szText);
private : //屏蔽函数
     LogFileEx( const  LogFileEx&);
     LogFileEx&operator = ( const  LogFileEx&);
};
#endif
1
  
1
cpp文件
1
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//---------------------------------------------------------------------------
 
 
#pragma hdrstop
 
#include "LogFileEx.h"
 
//---------------------------------------------------------------------------
 
#pragma package(smart_init)
//-------------------------------------------------------------------------
 
void  LogFileEx::SetPath( const  char  *szPath)
{
        assert (szPath);
 
        WIN32_FIND_DATA wfd;
        char  temp[MAX_PATH + 1] = {0};
 
        if (FindFirstFile(szPath, &wfd) == INVALID_HANDLE_VALUE && CreateDirectory(szPath, NULL) == 0)
        {
             strcat ( strcpy (temp, szPath), " Create Fail. Exit Now! Error ID :" );
             ltoa(GetLastError(), temp + strlen (temp), 10);
             MessageBox(NULL, temp, "Class LogFileEx" , MB_OK);
             exit (1);
        }
        else
        {
             GetFullPathName(szPath, MAX_PATH, temp, NULL);
             _szPath = new  char [ strlen (temp) + 1];
             assert (_szPath);
             strcpy (_szPath, temp);
        }
}
//-------------------------------------------------------------------------
LogFileEx::LogFileEx( const  char  *szPath , LOG_TYPE iType)
{
    _szPath = NULL;
    SetPath(szPath);
    _iType = iType;
    memset (_szLastDate, 0, 9);
}
//-------------------------------------------------------------------------
LogFileEx::~LogFileEx()
{
    if (_szPath)
     delete  []_szPath;
}
//-------------------------------------------------------------------------
 
const  char  * LogFileEx::GetPath()
{
    return  _szPath;
}
//-------------------------------------------------------------------------
 
void  LogFileEx::Log( LPCVOID  lpBuffer, DWORD  dwLength)
{
     assert (lpBuffer);
 
     char  temp[10];
     static  const  char  format[3][10] = { "%Y" , "%Y-%m" , "%Y%m%d" };
 
     __try
     {
         Lock();
 
         time_t  now = time (NULL);
 
         strftime (temp, 9, format[_iType], localtime (&now));
 
         if ( strcmp (_szLastDate, temp) != 0) //更换文件名
         {
             strcat ( strcpy (_szFileName, _szPath), "\\" );
             strcat ( strcat (_szFileName, temp), ".log" );
             strcpy (_szLastDate, temp);
             Close();
         }
         if (!OpenFile())
             return ;
 
         WriteLog(lpBuffer, dwLength);
     }
     __finally
     {
         Unlock();
     }
}
//-------------------------------------------------------------------------
void  LogFileEx::Log( const  char  *szText)
{
    Log(szText, strlen (szText));
}
//-------------------------------------------------------------------------
void  LogFileEx::Log( const  AnsiString&szText)
{
     Log(szText.c_str(),szText.Length());
}

 

3.随便测试的代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//---------------------------------------------------------------------------
 
#include <vcl.h>
#include <conio.h>
#include "LogFileEx.h"
#pragma hdrstop
 
//---------------------------------------------------------------------------
 
#pragma argsused
int  main( int  argc, char * argv[])
{
     LogFileEx log ;
     log .Log( "哈哈" );
     AnsiString temp= "adsfsadfsadfsaf" ;
     log .Log(temp);
     log .Log(temp);
     getch();
     return  0;
}
//---------------------------------------------------------------------------
1
  
相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
8月前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
388 2
|
9月前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
239 4
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
544 12
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
280 0
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
455 0
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
282 16
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
960 6