之前设备上需要保留各个组建的通讯协议帧,本来C++17已经提供了filesystem库实现,奈何编译器没有更新,不支持,只好用C的方式实现了,主要实现代码如下:
#include <windows.h>
#include <cstdio>
#include <string>
#include <iostream>
#include <memory>
#include <time.h>
#include <fcntl.h>
#include <corecrt_io.h>
#include <synchapi.h>
#include <sys/types.h>
#include <sys/stat.h> // 提供结构体 stat 的定义,用于获取文件信息
#define USER_LOG_PATH "d:\\fafiles\\test\\data\\log\\"
#define MAX_LOG_SIZE 32*1024 //内存中存满32K后,转存到文件中
#define MAX_LOGFILE_SIZE 1024*1024 //文件存满1M后,转存另外一个文件,本文件从头开始保存
typedef unsigned char BYTE;
typedef unsigned short WORD;
unsigned int m_dwLogOffset = 0;
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
typedef struct {
WORD nYear;
BYTE nMonth;
BYTE nDay;
BYTE nHour;
BYTE nMinute;
BYTE nSecond;
BYTE nWeek;
}TTime;
bool GetSysTime(TTime* pTime)
{
struct tm tCurTime;
time_t curtime;
curtime = time(NULL); //lt1
localtime_s(&tCurTime, &curtime);
pTime->nYear = tCurTime.tm_year + 1900;
pTime->nMonth = tCurTime.tm_mon + 1;
pTime->nDay = tCurTime.tm_mday;
pTime->nHour = tCurTime.tm_hour;
pTime->nMinute = tCurTime.tm_min;
pTime->nSecond = tCurTime.tm_sec;
pTime->nWeek = tCurTime.tm_wday;
if (pTime->nYear < 2000)
pTime->nYear = 2000;
return true;
}
void GetCurTime(TTime* pTime)
{
GetSysTime(pTime);
}
void HexToASCII(BYTE* in, BYTE* out, WORD wInLen)
{
for (WORD i = 0; i<wInLen; i++)
{
BYTE b = *in++;
BYTE hi = b >> 4;
BYTE lo = b & 0x0f;
if (hi >= 0x0a)
*out++ = hi - 0x0a + 'A';
else
*out++ = hi + '0';
if (lo >= 0x0a)
*out++ = lo - 0x0a + 'A';
else
*out++ = lo + '0';
}
}
std::string HexToString(BYTE* pbBuf, WORD wLen)
{
BYTE bBuf[2048]{ 0 };
string strFrm;
HexToASCII(pbBuf, bBuf, wLen);
for (int i = 0; i < wLen * 2; )
{
strFrm.push_back(bBuf[i++]);
strFrm.push_back(bBuf[i++]);
strFrm += " ";
}
return strFrm;
}
std::unique_ptr<BYTE> m_pLogBuf{ nullptr };
int SaveLog(string strLogName, BYTE bDr, BYTE* pbBuf, WORD wlen)
{
if (m_pLogBuf == nullptr || strLogName.empty())
return -1;
const string strLogFile = USER_LOG_PATH + strLogName;
TTime now;
GetCurTime(&now);
char cTimeHeader[16]{ 0 };
sprintf(cTimeHeader, "%02d %02d:%02d:%02d", now.nDay, now.nHour, now.nMinute, now.nSecond);
if (wlen > 650) //长度截取
wlen = 650;
string strlog;
if (bDr == 0) //发送帧
{
strlog = string(cTimeHeader) + "->" + HexToString(pbBuf, wlen) + "\n";
}
else
{
strlog = string(cTimeHeader) + "<-" + HexToString(pbBuf, wlen) + "\n";
}
if (m_dwLogOffset + strlog.size() >= MAX_LOG_SIZE - 1)
{
int fd_log = _open(strLogFile.c_str(), O_RDWR | O_CREAT, 0666);
if (fd_log < 0)
{
printf("SaveLog:Open %s failed!\r\n", strLogFile.c_str());
m_dwLogOffset = 0; //无法保存文件,直接就覆盖内存信息
return -1;
}
int nlogSize = _lseek(fd_log, 0L, SEEK_END); //获取本地最新log文件大小
if (nlogSize < 0)
{
printf("SaveLog:lseek %s failed!\r\n", strLogFile.c_str());
m_dwLogOffset = 0;
_close(fd_log);
return -1;
}
if (nlogSize + m_dwLogOffset > MAX_LOGFILE_SIZE)//超过当前文件大小500K
{
_close(fd_log);
string strlogbakfile = strLogFile + ".0";
int nLogBakFile = _open(strlogbakfile.c_str(), O_RDWR);
if (nLogBakFile >= 0)
{
_close(nLogBakFile);
remove(strlogbakfile.c_str());
Sleep(200);
}
rename(strLogFile.c_str(), strlogbakfile.c_str());
fd_log = _open(strLogFile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd_log < 0)
{
printf("SaveLog:re-open %s failed!\r\n", strLogFile.c_str());
m_dwLogOffset = 0;
return -1;
}
_lseek(fd_log, 0L, SEEK_SET);
}
int nWrRet = _write(fd_log, m_pLogBuf.get(), m_dwLogOffset);
if (nWrRet < 0)
{
printf("SaveLog:write %s failed!\r\n", strLogFile.c_str());
m_dwLogOffset = 0;
_close(fd_log);
return -1;
}
m_dwLogOffset = 0;
_close(fd_log);
}
memcpy(m_pLogBuf.get() + m_dwLogOffset, strlog.c_str(), strlog.size());
m_dwLogOffset += strlog.size();
return wlen;
}
int main()
{
m_pLogBuf.reset(new BYTE[MAX_LOG_SIZE]);
BYTE bRxBuf[] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
BYTE bTxBuf[] = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };
while (1)
{
SaveLog("test-log", 0, bRxBuf, sizeof(bRxBuf));
SaveLog("test-log", 1, bTxBuf, sizeof(bRxBuf));
Sleep(1000);
}
return 0;
}
以上代码VC编译没有问题,使用老的C方式实现确实有些low,但没办法,升级编译器是一个大工程,先用这个吧,正式使用没问题