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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 1.日志基类 .h文件//--------------------------------------------------------------------------- #ifndef UnitLogWriterH #define UnitLogWriterH #include ...

1.日志基类

.h文件

//---------------------------------------------------------------------------
#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文件

//---------------------------------------------------------------------------


#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();
       }
}
 

2.日志派生类

.h文件

//---------------------------------------------------------------------------

#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
 
cpp文件
 
//---------------------------------------------------------------------------


#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.随便测试的代码

 

//---------------------------------------------------------------------------

#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;
}
//---------------------------------------------------------------------------
 
相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
1月前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
2月前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
120 4
|
8月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
247 2
|
11月前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
254 1
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
502 5
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
177 1
C++ 多线程之初识多线程
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
831 7
|
消息中间件 存储 安全
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
267 5
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
496 6