功能:
1:将log 日志保存到文件
2:文件名字以时间戳命名
3:可以自动删除老的日志文件
4:可以设置每个日志文件的大小 5M或者其他
源码提供,超级简单,可以非常简单的添加到工程中,终于不用配一些第三方库了
共两个文件
myLog.h myLog.cpp
测试文件为
main.cpp
myLog.h
#ifndef __myLog_H_
#define __myLog_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <ratio>
#include <chrono>
#include <mutex>
#define CLAMPXX(a, s, m) ((a) < (s)? (s) : ((a) > (m) ? (m) : (a)))
std::string GetName(const char * fileName);
std::string getCurrentSystemTime();
long long getCurrentMs();
int LOGINIT();
int LOGEnd();
int LOGSetMaxSpace(int mSize);
int logWrite(char * s);
#define LOGEM(...) {\
char temp[8192] = {0}; \
sprintf(temp, "%s", getCurrentSystemTime().c_str()); \
sprintf(temp+strlen(temp), " %s %d ", GetName(__FILE__).c_str(), __LINE__); \
sprintf(temp+strlen(temp), __VA_ARGS__); \
sprintf(temp + strlen(temp), "\n"); \
printf("%s", temp); \
logWrite(temp); \
}
#endif
myLog.cpp
//#include "Config.h"
#define OS_S OS_Linux
#include "myLog.h"
#include <vector>
#include <string>
#include <fstream>
#define OS_Linux 0
#define OS_Windows 1
#define OS_iOS 2
#if OS_S==OS_Linux
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <malloc.h>
#include <dirent.h>
#elif OS_S== OS_iOS
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#elif OS_S == OS_Windows
#include <io.h>
#include <direct.h>
#endif
std::string dumpRoot = "./cpplog"; //
std::mutex mux;
static FILE * fp = NULL;
int MaxLenChar = 1024 * 1024 * 10; // , 1024 * 1024 * 5
int MaxLogNum = 5;
static int com(const void *a, const void *b)
{
long long * p1, *p2;
p1 = (long long *)a; //
p2 = (long long *)b; //
return *p1 > *p2 ? 1 : -1;
}
void GetAllFiles(std::string path, std::vector<std::string>& files)
{
intptr_t hFile = 0;
#if OS_S == OS_Windows
struct _finddata_t fileinfo;//
std::string p;
if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) //
{
do
{
if ((fileinfo.attrib & _A_SUBDIR)) //
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) //
{
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
GetAllFiles(p.assign(path).append("\\").append(fileinfo.name), files);
}
}
else //
{
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile); //
}
#elif OS_S == OS_Linux
dirent * dirt; // linux
DIR * dir;;
char *s[100];
int i = 0, n = 1;
int onePathLen = 256;
s[0] = new char[onePathLen];
memset(s[0], 0, onePathLen);
sprintf(s[0], "%s", path.c_str());
do {
dir = opendir(s[i]); //
//
if (dir != NULL)
{
while ((dirt = readdir(dir)) != NULL) { //
//
if (strcmp(dirt->d_name, ".") == 0 || strcmp(dirt->d_name, "..") == 0)
continue;
s[n] = new char[onePathLen];
memset(s[n], 0, onePathLen);
sprintf(s[n], "%s/%s", s[i], dirt->d_name);
n++;
}
}
i++;
} while (i < n);
for (i = 1; i < n; i++) //
{
printf("%s\n", s[i]);
std::string temp = s[i];
files.push_back(temp);
}
closedir(dir);
while (n--) {
//remove(s[n]);
delete[]s[n];
}
#endif
}
//
void GetName(std::vector<std::string> &vPath, std::vector<std::string> &vName)
{
if (vPath.size() <= 0)
{
printf("vPath.size <= 0");
return;
}
for (int i = 0; i < vPath.size(); i++)
{
std::string path = vPath[i];
int pointDot = path.find_last_of('.');
#if OS_S == OS_Windows
int pointN = path.find_last_of('\\');
#elif OS_S == OS_Linux
int pointN = path.find_last_of('/');
#endif
std::string name = path.substr(pointN + 1, pointDot - pointN - 1);
vName.push_back(name);
}
}
static int removeOldFile(std::string &rootPath)
{
std::vector<std::string> files;
std::vector<long long> filesNum;
GetAllFiles(rootPath, files);
printf("rootPath = %s files.size = %d \n", rootPath.c_str(), files.size());
if (files.size() > MaxLogNum)
{
for (int i = 0; i < files.size(); i++)
{
int pos0 = files[i].find("LOG_");
std::string cut = files[i].substr(pos0 + 4, files[i].size());
char* endptr = NULL;
long long num = std::strtoll(cut.c_str(), &endptr, 10);
printf("cut = %s num = %lld \n", cut.c_str(), num);
filesNum.push_back(num);
}
qsort(&filesNum.data()[0], filesNum.size(), sizeof(long long), com);
//
printf(" delete num = %d \n", filesNum.size() - 5);
long long deleteNum = filesNum.size() - MaxLogNum;
for (int i = 0; i < deleteNum; i++)
{
std::string logPath = rootPath + std::string("/LOG_") + std::to_string(filesNum[i]);
printf("删除文件= %s \n", logPath.c_str());
remove(logPath.c_str());
}
}
return 0;
}
int dump_init_temp() {
#undef FUNC_CODE
#define FUNC_CODE 0x01
//create dump folder
#if OS_S==OS_Windows
if (_access(dumpRoot.c_str(), 00) != 0) {
_mkdir(dumpRoot.c_str());
#else
if (access(dumpRoot.c_str(), 00) != 0) {
mkdir(dumpRoot.c_str(), S_IRWXU);
#endif
}
return 0;
}
int LOGINIT()
{
dump_init_temp();
removeOldFile(dumpRoot);
long long currentMs = getCurrentMs();
char currentMsStr[20];
sprintf(currentMsStr,"%lld", currentMs);
std::string logPath = dumpRoot + "/LOG_" + currentMsStr;
fp = NULL;
fp = fopen(logPath.c_str(), "w+");
if (fp == NULL)
{
return -1;
}
return 0;
}
int LOGSetMaxSpace(int mSize)
{
MaxLenChar = mSize;
return 0;
}
int logWrite(char * s)
{
if (fp)
{
int len = ftell(fp);
if (len > MaxLenChar)
{
LOGEnd();
LOGINIT();
return 0;
}
mux.lock();
fprintf(fp, "%s", s);
fflush(fp);
mux.unlock();
}
return 0;
}
int LOGEnd()
{
if (fp)
{
fflush(fp);
fclose(fp);
fp = 0;
}
return 0;
}
std::string getCurrentSystemTime()
{
auto time_now = std::chrono::system_clock::now();
auto tt = std::chrono::system_clock::to_time_t(time_now);
auto duration_in_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_now.time_since_epoch());
auto duration_in_s = std::chrono::duration_cast<std::chrono::seconds>(time_now.time_since_epoch());
int theMs = duration_in_ms.count() - duration_in_s.count() * 1000;
struct tm* ptm = localtime(&tt);
char date[60] = { 0 };
sprintf(date, "%d-%02d-%02d-%02d.%02d.%02d.%03d%",
(int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday,
(int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec, theMs);
return std::string(date);
}
long long getCurrentMs()
{
auto time_now = std::chrono::system_clock::now();
auto duration_in_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_now.time_since_epoch());
return duration_in_ms.count();
}
std::string GetName(const char * fileName)
{
char temp[256] = { 0 };
memcpy(temp, fileName, strlen(fileName) + 1);
std::string sName = temp;
#ifdef WIN32
int startP = sName.find_last_of("\\");
if (startP == -1)
{
startP = 0;
}
std::string theLastName = sName.substr(startP + 1, sName.size() - startP);
#else
int startP = sName.find_last_of("/");
if (startP == -1)
{
startP = 0;
}
std::string theLastName = sName.substr(startP + 1, sName.size() - startP);
#endif
return theLastName;
}
main.cpp
#include <stdio.h>
#include "myLog.h"
//#include "GetFileName.h"
int main()
{
LOGINIT();
for(int i = 0; i < 1000000; i ++)
{
LOGE("i = %d ... \n", i);
}
LOGEnd();
return 0;
}
输出文件结果
2019-03-20-19.57.57.278 main.cpp 12 i = 3521 …
2019-03-20-19.57.57.278 main.cpp 12 i = 3522 …
2019-03-20-19.57.57.278 main.cpp 12 i = 3523 …
2019-03-20-19.57.57.279 main.cpp 12 i = 3524 …
2019-03-20-19.57.57.282 main.cpp 12 i = 3525 …
2019-03-20-19.57.57.283 main.cpp 12 i = 3526 …
修改最上面的文件GetFileName.h, 可以支持在linux 下面
#ifndef GETFILENAME_H_
#define GETFILENAME_H_
#include "Config.h"
#if OS_S == OS_Windows
#include <io.h>
#elif OS_S == OS_Linux
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#endif
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
void GetAllFiles(std::string path, std::vector<std::string>& files)
{
intptr_t hFile = 0;
//文件信息
#if OS_S == OS_Windows
struct _finddata_t fileinfo;//用来存储文件信息的结构体
std::string p;
if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) //第一次查找
{
do
{
if ((fileinfo.attrib & _A_SUBDIR)) //如果查找到的是文件夹
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) //进入文件夹查找
{
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
GetAllFiles(p.assign(path).append("\\").append(fileinfo.name), files);
}
}
else //如果查找到的不是是文件夹
{
//files.push_back(p.assign(fileinfo.name)); //将文件路径保存,也可以只保存文件名: p.assign(path).append("\\").append(fileinfo.name)
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile); //结束查找
}
#elif OS_S == OS_Linux
dirent * dirt; // linux 下的结构体
DIR * dir;;
char *s[100];
int i = 0, n = 1;
int onePathLen = 256;
s[0] = new char[onePathLen];
memset(s[0], 0, onePathLen);
sprintf(s[0], "%s", path.c_str());
do {
dir = opendir(s[i]); // 打开指定路径
//printf("0000000000000 s[0]=%s \n", path);
if (dir != NULL)
{
while ((dirt = readdir(dir)) != NULL) { // 存储路径下的所有文件和文件夹路径
//printf("111111111111");
if (strcmp(dirt->d_name, ".") == 0 || strcmp(dirt->d_name, "..") == 0)
continue;
s[n] = new char[onePathLen];
memset(s[n], 0, onePathLen);
sprintf(s[n], "%s/%s", s[i], dirt->d_name);
n++;
}
}
i++;
} while (i < n);
for (i = 1; i < n; i++) // 广度优先遍历文件夹
{
printf("%s\n", s[i]);
std::string temp = s[i];
files.push_back(temp);
}
closedir(dir);
while (n--) {
//remove(s[n]);
delete[]s[n];
}
#endif
}
// 在路径中提取文件的名字
void GetName(std::vector<std::string> &vPath, std::vector<std::string> &vName)
{
if (vPath.size() <= 0)
{
printf("vPath.size <= 0");
return;
}
for (int i = 0; i < vPath.size(); i++)
{
std::string path = vPath[i];
int pointDot = path.find_last_of('.');
#if OS_S == OS_Windows
int pointN = path.find_last_of('\\');
#elif OS_S == OS_Linux
int pointN = path.find_last_of('/');
#endif
std::string name = path.substr(pointN + 1, pointDot - pointN - 1);
vName.push_back(name);
}
}
#endif