C/C++语言log日志框架

编译器:VisualStudio 2019

C++标准:C++17

.h文件

#pragma once
/*
#define _CRT_SECURE_NO_WARNINGS
添加这宏定义来禁用备份函数的警告,
例如:sprintf,mkdir,fopen。
如果不用这个则需要修改函数,
例如:sprintf_s,_mkdir,fopen_s。
*/
#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
/*MacOS Linux 系统用<sys/stat.h> / Windows系统用 <direct.h>*/
#include <direct.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>

#include<iostream>
#include <vector>
#include <filesystem>
#include <algorithm>

using namespace std;
namespace fs = std::filesystem;
using namespace std::chrono;

class Logger
{
private:
	int isSaveInFile;
	int saveMonth;
	char folderPath[64];
	int FileIsExist(char* folderPath, char* filename);
	int autoClearLogs;
public:
	Logger();
	Logger(int isSaveInFile, const char* folderPath, int saveMonth = 3, int autoClearLogs = 1);
	~Logger();
	void Init(int isSave, const char* folderPath, int saveMonth = 3, int autoClearLogs = 1);
	void Error(const char* format, ...);
	void Warn(const char* format, ...);
	void Info(const char* format, ...);
	void Debug(const char* format, ...);
	void CleanOldLogs();
};

.cpp文件

#include "Logger.h"
/*
* 判断日志文件是否存在
* @param folderPath:文件夹,filename:文件名
* @retval 0:文件不存在并且创建失败,1:文件存在或者创建成功
*/
int Logger::FileIsExist(char* folderPath, char* filename)
{
    int result = 0;
    char filepath[100]; // 完整的文件路径
    sprintf(filepath, "%s\\%s", folderPath, filename); // 拼接文件路径
    if (_mkdir(folderPath) == -1) // 检查文件夹是否存在,如果不存在则创建
    {
        //printf("文件夹已存在或创建失败\n");
    }
    else
    {
        //printf("文件夹已创建\n");
    }
    FILE* file = fopen(filepath, "r");// 尝试打开文件
    if (file == NULL)
    {
        file = fopen(filepath, "w"); // 如果文件不存在,则创建文件
        if (file != NULL)
        {
            fclose(file); //printf("文件已创建\n");
            if (this->autoClearLogs!=0)//如果启动了文件自动清理,则清理过期文件
            {
                CleanOldLogs();
            }
            result = 1;
        }
        else
        {
            //printf("文件创建失败\n");
            result = 0;
        }
    }
    else
    {
        //printf("文件已存在\n");
        result = 1;
        fclose(file);
    }
    return result;
}

Logger::Logger()
{
	char path[64] = "Log";
	this->Init(0, path, 0, 0);
}

Logger::Logger(int isSaveInFile, const char* folderPath, int saveMonth, int autoClearLogs)
{
	this->Init(isSaveInFile, folderPath, saveMonth, autoClearLogs);
}

Logger::~Logger()
{
}
/*
* 初始化日志系统
* @param isSave:是否保存到文件,folderPath:文件夹,saveMonth:保存几个月(默认3个月),autoClearLogs:是否开启自动清理(默认开启)
* @retval 无
*/
void Logger::Init(int isSave, const char* folderPath, int saveMonth, int autoClearLogs)
{
    this->isSaveInFile = isSave;
    strcpy(this->folderPath, folderPath);
    this->saveMonth = saveMonth;
    this->autoClearLogs = autoClearLogs;
    if (this->isSaveInFile)
    {
        struct tm timeinfo;
        time_t rawtime;
        time(&rawtime);
        localtime_s(&timeinfo, &rawtime);
        char filename[16];
        sprintf(filename, "%d-%02d-%02d.log", timeinfo.tm_year + 1900,timeinfo.tm_mon + 1, timeinfo.tm_mday);
        if (this->FileIsExist(this->folderPath,filename))
        {
            char filepath[128] = "";
            sprintf(filepath, "%s/%s", this->folderPath, filename);
            FILE* file = fopen(filepath, "a");
            if (file != NULL) {
                fclose(file);
                printf("启用日志输出,日志位置: /%s\n", filepath);
            }
            else
            {
                printf("日志文件异常!\n");
            }
        }
        else
        {
            printf("日志文件异常!\n已关闭日志输出,启用控制台输出。\n");
            this->isSaveInFile = 0;
        }
    }
    else
    {
        printf("启用控制台输出。\n");
    }
}
/*
* 输出Error信息
*/
void Logger::Error(const char* format, ...)
{
    va_list args;
    struct tm timeinfo;
    time_t rawtime;
    time(&rawtime);
    localtime_s(&timeinfo, &rawtime);
    va_start(args, format);
    if (this->isSaveInFile)
    {
        char filename[24];
        sprintf(filename, "%d-%02d-%02d.log", timeinfo.tm_year + 1900,timeinfo.tm_mon + 1, timeinfo.tm_mday);
        if (FileIsExist(this->folderPath, filename))
        {
            char filepath[128] = "";
            sprintf(filepath, "%s/%s", this->folderPath, filename);
            FILE* file = fopen(filepath, "a");
            if (file)
            {
                char headInfo[128];
                sprintf(headInfo, "Aplication run at %02d:%02d:%02d Error: ",timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
                vfprintf(file, headInfo, 0);
                vfprintf(file, format, args);
                vfprintf(file, "\n", 0);
                fclose(file);
            }
        }
    }
    else
    {
        char headInfo[128];
        sprintf(headInfo, "Aplication run at %02d:%02d:%02d Error: [",timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
        vprintf(headInfo, 0);
        vprintf(format, args);
        vprintf("]\n", 0);
    }
    va_end(args);
}
/*
* 输出Warn信息
*/
void Logger::Warn(const char* format, ...)
{
    va_list args;
    struct tm timeinfo;
    time_t rawtime;
    time(&rawtime);
    localtime_s(&timeinfo, &rawtime);
    va_start(args, format);
    if (this->isSaveInFile)
    {
        char filename[24];
        sprintf(filename, "%d-%02d-%02d.log", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
        if (FileIsExist(this->folderPath, filename))
        {
            char filepath[128] = "";
            sprintf(filepath, "%s/%s", this->folderPath, filename);
            FILE* file = fopen(filepath, "a");
            if (file)
            {
                char headInfo[128];
                sprintf(headInfo, "Aplication run at %02d:%02d:%02d Warn: ", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
                vfprintf(file, headInfo, 0);
                vfprintf(file, format, args);
                vfprintf(file, "\n", 0);
                fclose(file);
            }
        }
    }
    else
    {
        char headInfo[128];
        sprintf(headInfo, "Aplication run at %02d:%02d:%02d Warn: [", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
        vprintf(headInfo, 0);
        vprintf(format, args);
        vprintf("]\n", 0);
    }
    va_end(args);
}
/*
* 输出Info信息
*/
void Logger::Info(const char* format, ...)
{
    va_list args;
    struct tm timeinfo;
    time_t rawtime;
    time(&rawtime);
    localtime_s(&timeinfo, &rawtime);
    va_start(args, format);
    if (this->isSaveInFile)
    {
        char filename[24];
        sprintf(filename, "%d-%02d-%02d.log", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
        if (FileIsExist(this->folderPath, filename))
        {
            char filepath[128] = "";
            sprintf(filepath, "%s/%s", this->folderPath, filename);
            FILE* file = fopen(filepath, "a");
            if (file)
            {
                char headInfo[128];
                sprintf(headInfo, "Aplication run at %02d:%02d:%02d Info: ", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
                vfprintf(file, headInfo, 0);
                vfprintf(file, format, args);
                vfprintf(file, "\n", 0);
                fclose(file);
            }
        }
    }
    else
    {
        char headInfo[128];
        sprintf(headInfo, "Aplication run at %02d:%02d:%02d Info: [", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
        vprintf(headInfo, 0);
        vprintf(format, args);
        vprintf("]\n", 0);
    }
    va_end(args);
}
/*
* 输出Debug信息
*/
void Logger::Debug(const char* format, ...)
{
    va_list args;
    struct tm timeinfo;
    time_t rawtime;
    time(&rawtime);
    localtime_s(&timeinfo, &rawtime);
    va_start(args, format);
    if (this->isSaveInFile)
    {
        char filename[24];
        sprintf(filename, "%d-%02d-%02d.log", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
        if (FileIsExist(this->folderPath, filename))
        {
            char filepath[128] = "";
            sprintf(filepath, "%s/%s", this->folderPath, filename);
            FILE* file = fopen(filepath, "a");
            if (file)
            {
                char headInfo[128];
                sprintf(headInfo, "Aplication run at %02d:%02d:%02d Debug: ", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
                vfprintf(file, headInfo, 0);
                vfprintf(file, format, args);
                vfprintf(file, "\n", 0);
                fclose(file);
            }
        }
    }
    else
    {
        char headInfo[128];
        sprintf(headInfo, "Aplication run at %02d:%02d:%02d Debug: [", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
        vprintf(headInfo, 0);
        vprintf(format, args);
        vprintf("]\n", 0);
    }
    va_end(args);
}
/*
* 清理saveMonth个月前的log文件
* @param 无
* @retval 无
*/
void Logger::CleanOldLogs()
{
    vector<string> log_files;
    for (const auto& entry : std::filesystem::directory_iterator(this->folderPath))
    {
        if (entry.is_regular_file() && entry.path().extension() == ".log")
        {
            log_files.push_back(entry.path().string());
        }
    }
    try
    {
        int num = (int)log_files.size();
        int saveFileNum = this->saveMonth * 30;
        if (num > saveFileNum)
        {
            sort(log_files.begin(), log_files.end());
            for (int i = 0; i < num - saveFileNum; ++i)
            {
                filesystem::remove(log_files[i]);
            }
            this->Warn("日志文件已清理!");
        }
    }
    catch (const exception& e)
    {
        this->Error("清理日志文件时出现异常: ");
        this->Error(e.what());
        this->Error("\r\n--------------------------\r\n");
    }
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值