C方式实现文件保存

发布时间:2023年12月22日

之前设备上需要保留各个组建的通讯协议帧,本来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,但没办法,升级编译器是一个大工程,先用这个吧,正式使用没问题

文章来源:https://blog.csdn.net/weixin_45119096/article/details/134955516
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。