Ya土豆儿~ 2022-01-17 13:29 采纳率: 0%
浏览 44

windows下如何实现高效的C的log日志记录

我想要达到的结果

windows下如何实现高效的C的log日志记录

  • 写回答

1条回答 默认 最新

  • 关注

    开个线程,用fprintf写文件就是了
    下面是我很久之前封装的一个日记工具接口,生成dll后直接调用dll接口就可以了
    MyLog.h

    #ifndef _TZHYJSGLB_LOG_H_
    #define _TZHYJSGLB_LOG_H_
    
    #include <stdlib.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <string>
    #include <queue>
    #include <string.h>
    #include <Windows.h>
    #include <process.h>
    #include <time.h>
    #ifdef LCLOG_API
    
    #else
    #define LCLOG_API _declspec(dllimport)
    
    #endif
    
    /**@类名:日志管理类
     * @职责:生成并管理日志
     * @功能:
     */
    //日志文件模式:每天一个日志文件,每月一个日志文件,只有一个日志文件
    enum EMyLogModle
    {
        EL_EVERY_DAY,
        EL_EVERY_MON,
        EL_ONLYONE
    };
    
    class LCLOG_API CMyLog
    {
    protected:
        CMyLog();
        ~CMyLog();
    public:
        /**@brief:初始化日志管理类
         * @param[in] strLogPath:日志存放路径,不含日志名称
         * @return:
         * @remark:
         */
        static void Init(std::string strLogPath);
    
        /**@brief:设置日志文件模式
         * @param[in] eMod:日志模式
         * @param[in] strFileName:日志文件名称,日志模式为EL_ONLYONE时,填写该参数
         * @return:
         * @remark:
         */
        static void SetLogFileModle(EMyLogModle eMod,std::string strFileName ="");
    
        /**@brief:写入日志
         * @param[in]:日志内容
         * @return:
         * @remark:
         */
        static std::string NewLog(std::string strLog);
        static std::string NewLog(const char* pszFormat,...);
    
        /**@brief:释放资源
         * @param[]
         * @return:
         * @remark:
         */
        static void Release();
    private:
        static std::string LogOutQueue();                    //日志出队
        static void* CreateLogFile(void*);                   //创建日志文件
        static void GetLogFile();                            //获取日志文件指针
        static bool IsNeedNewFile(std::string strFile);      //判断是否需要新的日志文件
        static std::string GetTime();                        //获取当时时间
    private:
        static std::string m_strLogPath;                     //日志文件路径
        static std::string m_strSingleLogName;               //单日志文件名称
        static std::string m_strCurrentLog;                  //当前日志文件名称
        static EMyLogModle m_eModle;                         //日志文件类型
        static std::queue<std::string>* m_pqLogManager;      //日志管理队列
        static HANDLE m_mutexQueue;                          //日志队列锁
        static FILE* m_Filelog;                              //日志文件
        //static char m_cTmp[1024];                            //缓冲区
        static HANDLE m_hWnd;                                //日志线程ID
    };
    #endif
    
    

    MyLog.cpp

    //日志管理类实现
    #ifdef WIN32
    #define LCLOG_API _declspec(dllexport)
    #endif
    
    
    #include "MyLog.h"
    
    
    //////////////////////////////////////////////////////////////////////////////////////
    //                                 静态变量                                         //
    //////////////////////////////////////////////////////////////////////////////////////
    std::string CMyLog::m_strLogPath;                     //日志文件路径
    std::string CMyLog::m_strSingleLogName;               //单日志文件名称
    std::string CMyLog::m_strCurrentLog;                  //当前日志文件名称
    EMyLogModle CMyLog::m_eModle;                         //日志文件类型
    std::queue<std::string>* CMyLog::m_pqLogManager;      //日志管理队列
    HANDLE CMyLog::m_mutexQueue;                          //日志队列锁
    FILE* CMyLog::m_Filelog;                              //日志文件
    //char CMyLog::m_cTmp[1024];                            //缓冲区
    HANDLE CMyLog::m_hWnd;                                //日志线程ID
    
    CMyLog::CMyLog(){}
    CMyLog::~CMyLog(){}
    
    //////////////////////////////////////////////////////////////////////////////////////
    //                                 对外接口                                         //
    //////////////////////////////////////////////////////////////////////////////////////
    //初始化日志管理类相关成员
    void CMyLog::Init(std::string strLogPath)
    {
        //默认为每天一个日志文件
        m_eModle = EL_EVERY_DAY;
        //清空日志队列
        m_pqLogManager = NULL;
        m_pqLogManager = new std::queue<std::string>;
        //初始化互斥锁
        m_mutexQueue = ::CreateMutex(NULL, FALSE, NULL);
        //初始化日志文件
        m_Filelog = NULL;
        m_strLogPath = strLogPath;
        m_strSingleLogName = "";
        m_strCurrentLog = " ";
        //memset(m_cTmp,0,1024);
        //启动日记线程
        m_hWnd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateLogFile, NULL, 0, 0);
    }
    //设置日志文件模式
    void CMyLog::SetLogFileModle( EMyLogModle eMod ,std::string strFileName)
    {
        m_eModle = eMod;
        if (eMod == EL_ONLYONE)
        {
            m_strSingleLogName = strFileName;
        }
    }
    //写入日志
    std::string CMyLog::NewLog( std::string strLog )
    {
        std::string strTime = GetTime();
        strTime += strLog;
        WaitForSingleObject(m_mutexQueue, INFINITE);
        m_pqLogManager->push(strTime);//strLog
        ::ReleaseMutex(m_mutexQueue);
        return strLog;
    }
    //写入日志
    std::string CMyLog::NewLog( const char* pszFormat,... )
    {
        //WINDOWS
        //va_list args;
        //int     len = 0;
    
        //// retrieve the variable arguments
        //va_start( args, pszFormat );
    
        //len = _vscprintf( pszFormat, args ) +1;// _vscprintf doesn't count terminating '\0'
    
        //char* buffer = new char[len * sizeof(char)];
        //memset(buffer,0,len * sizeof(char));
        //vsprintf( buffer, pszFormat, args ); // C4996
        //// Note: vsprintf is deprecated; consider using vsprintf_s instead
        //
        //std::string strTmp = (std::string)buffer;
        //NewLog(strTmp);
        //delete []buffer;
        //buffer = NULL;
        //LINUX
        va_list args;
        va_start( args, pszFormat );
        char cTmp[1024] ={0};
        //memset(m_cTmp,0,1024);
        int nRes = vsprintf(cTmp, pszFormat, args );
        va_end(args);
        //printf("%s\n",m_cTmp);
        std::string strTmp =(std::string)cTmp;
        NewLog(strTmp);
        return strTmp;
    }
    void CMyLog::Release()
    {
        TerminateThread(m_hWnd, 0);//结束日志线程
        //清空队列
        if (m_pqLogManager != NULL)
        {
            WaitForSingleObject(m_mutexQueue,INFINITE);
            while(m_pqLogManager->size() > 0)
            {
                m_pqLogManager->pop();
            }
            ::ReleaseMutex(m_mutexQueue);
            delete m_pqLogManager;
            m_pqLogManager = NULL;
        }
        ::CloseHandle(m_mutexQueue);
    }
    
    
    
    //////////////////////////////////////////////////////////////////////////////////////
    //                                 内部成员函数                                     //
    //////////////////////////////////////////////////////////////////////////////////////
    //日志出队
    std::string CMyLog::LogOutQueue()
    {
        std::string strLog = "";
        WaitForSingleObject(m_mutexQueue, INFINITE);
        strLog = m_pqLogManager->front();
        m_pqLogManager->pop();
        ::ReleaseMutex(m_mutexQueue);
        return strLog;
    }
    //创建日志文件:后台线程
    void* CMyLog::CreateLogFile(void*)
    {
        while(1)
        {
            if (m_pqLogManager == NULL)
            {
                return NULL;
            }
            if (m_pqLogManager->size() == 0)
            {
                Sleep(500);
            }else
            {
                //获取日志信息
                std::string strLog = LogOutQueue();
                //获取日志文件信息
                GetLogFile();
                //日志写入日志文件
                if (m_Filelog != NULL)
                {
                    fwrite(strLog.c_str(),strLog.length(),1,m_Filelog);
                    fflush(m_Filelog);
                    /*fclose(m_Filelog);
                    m_Filelog = NULL;*/
                }
            }
        }
    }
    
    //获取日志文件指针
    void CMyLog::GetLogFile()
    {
        if (m_eModle == EL_ONLYONE)//单一日志模式
        {
            if (m_Filelog == NULL)
            {
                std::string strFileNameOnly = m_strLogPath + m_strSingleLogName;
                m_Filelog = fopen(strFileNameOnly.c_str(),"a+");
            }else
                return;
        }else//其他模式
        {
            //获取当天日期
            time_t now;
            struct tm* timeinfo;
            time(&now);
            timeinfo = localtime(&now);
            std::string strTmp = "";
            char cTmp[15];
            memset(cTmp,0,15);
            //根据模式判断是否需要更换日志文件
            if (m_eModle == EL_EVERY_MON)
            {
                sprintf(cTmp,"%4d%02d.log",(int)1900+timeinfo->tm_year,(int)1+timeinfo->tm_mon);    
            }else if (m_eModle == EL_EVERY_DAY)
            {
                sprintf(cTmp,"%4d%02d%02d.log",(int)1900+timeinfo->tm_year,(int)1+timeinfo->tm_mon,(int)timeinfo->tm_mday);
            }else
                return;
            
            if (IsNeedNewFile(cTmp))//需要重新生成日志文件
            {
                if (m_Filelog != NULL)//如果原始日志文件未关闭
                {
                    fclose(m_Filelog);
                    m_Filelog = NULL;
                }
                //重新生成日志文件
                m_strCurrentLog = (std::string)cTmp;
                std::string strFileName = m_strLogPath + m_strCurrentLog;
                m_Filelog = fopen(strFileName.c_str(),"a+");
            }else
                return;
        }
        return;
    }
    //判断是否需要新的日志文件
    bool CMyLog::IsNeedNewFile(std::string strFile)
    {
        if (m_Filelog == NULL)//日志指针为空
        {
            return true;
        }else
        {
            if (m_strCurrentLog.compare(" ") == 0)//还没有生成过日志文件
            {
                return true;
            }else//生成过日志文件
            {
                if (m_strCurrentLog.compare(strFile.c_str()) == 0)//跟当前日期相同,不需要重新生成
                {
                    return false;
                }else//跟当前日期不同,需要重新生成
                    return true;
            }
        }
        
    }
    
    //获取时间
    std::string CMyLog::GetTime()
    {
        time_t tmNow = time(NULL);
        struct tm *local;
        local = localtime(&tmNow);
        char cTmp[22] = {0};
        sprintf(cTmp,"%d-%d-%d %d:%d:%d ",local->tm_year+1900,local->tm_mon+1,local->tm_mday,local->tm_hour,local->tm_min,local->tm_sec);
        return (std::string)cTmp;
    }
    
    
    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 1月17日