当前位置: 首页 > news >正文

一个环形的文件存储算法

可以实现数据在文件中的环形存储以及读取,使用了两个文件对索引以及具体的数据进行存储;

写入文件按照index_c索引指定区域指定长度写入;

读取文件通过以下代码进行计算,找到应该读取的索引

//应读取索引=(当前写入的索引-当前存储的总条数+最多能存储的条数)%最多能存储的条数
offline_ni.index_r = (offline_ni.index_c-offline_ni.all_num+OFFLINE_DATA_SAVE_NUM)%OFFLINE_DATA_SAVE_NUM;

例:

        当存储总条数为10,应写入索引为10时,这时读取数据时读取的索引应该为0;

        当已经读取一条数据后,存储的总条数就为9,应写入的索引不变,这时读取数据时读取的索引应该为1;

        当再次写入一条数据后,存储的总条数为10,当前写入的索引变为11,这时读取数据时读取索引应不变还是为1;

        当存储数据达到我们设定的最大存储条数4000时,写入的索引为4001,这时读取数据时读取索引保持之前的1;

        当继续写入数据,存储总条数不变,写入索引累加(4002、4003),这时存储的数据应该覆盖最开始存储的数据,读取索引也应累计(2、3),这时读取数据后,存储总条数变为3999,应写入索引不变,应读取索引加1变为4。

image

读取后,存储的总条数应该减1,由于该算法没有将读取后文件进行删除,在读取完所有数据后,也就是all_num等于0时,需要将保存具体数据的文件清空或者删除

if(offline_ni.all_num != 0)offline_ni.all_num--;    if(offline_ni.all_num == 0)
{//数据读完了,把数据清掉offline_ni.index_c = 0;offline_ni.index_r = 0;//需要清理掉文件中的具体数据
    Offline_data_file_clean();
}

下面是完整的代码:

#define OFFLINE_DATA_SAVE_NUM    4000        //可以存储的总条数
#define OFFLINE_DATA_FILE_D_PATH    "c:/offline1.bin"        //保存具体的数据
#define OFFLINE_DATA_FILE_N_PATH    "c:/offline2.bin"        //保存存储的条数以及写入的索引typedef struct
{UINT32 all_num;        //已存储总条数UINT32 index_c;        //当前索引(写)UINT32 index_r;        //读取的索引
}Offline_N;typedef struct
{UINT8 len;        //数据的长度UINT8 data[50];    //数据
}Offline_D;Offline_N offline_ni = {0};
Offline_D offline_data = {0};//检查是否还有数据
BOOL Offline_check_is_data(void)
{if(offline_ni.all_num == 0)return FALSE;return TRUE;
}//读取保存的条数以及写入的索引
void Offline_data_get_num(void)
{SCFILE *file_hdl = NULL;UINT8 err_code = 0;int read_len = 0;file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_N_PATH,"rb");if(file_hdl == NULL){err_code = 2;goto end;}sAPI_Debug("Offline_data_get_num %s sAPI_fsize %d",OFFLINE_DATA_FILE_N_PATH,sAPI_fsize(file_hdl));read_len = sAPI_fread(&offline_ni,1,sizeof(Offline_N),file_hdl);if(read_len <= 0){sAPI_fclose(file_hdl);err_code = 3;goto end;}sAPI_fclose(file_hdl);end:if(err_code == 0){sAPI_Debug("Offline_data_get_num read success");sAPI_Debug("Offline_data_get_num all_num = %d,index_c = %d",offline_ni.all_num,offline_ni.index_c);}else{sAPI_Debug("Offline_data_get_num read failed err_code = %d",err_code);}
}//mode = 0增加数据; mode = 1减少数据;mode = 其他值,不用读写文件
UINT8 Offline_data_write_num(UINT8 mode)
{SCFILE *file_hdl = NULL;UINT8 err_code = 0;int write_len = 0;UINT32 old_index_c = offline_ni.index_c;UINT32 old_all_num = offline_ni.all_num;//不用读写if(mode >= 2){goto end;}file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_N_PATH,"wb");if(file_hdl == NULL){err_code = 1;goto end;}if(mode == 0){offline_ni.index_c++;offline_ni.all_num++;if(offline_ni.index_c >= 2*OFFLINE_DATA_SAVE_NUM){offline_ni.index_c = offline_ni.index_c%OFFLINE_DATA_SAVE_NUM+OFFLINE_DATA_SAVE_NUM;}if(offline_ni.all_num >= OFFLINE_DATA_SAVE_NUM){offline_ni.all_num = OFFLINE_DATA_SAVE_NUM;}sAPI_Debug("Offline_data_write_num write all_num = %d,index_c = %d",offline_ni.all_num,offline_ni.index_c);}else if(mode == 1){if(offline_ni.all_num != 0)offline_ni.all_num--;    if(offline_ni.all_num == 0){//数据读完了,把数据清掉offline_ni.index_c = 0;offline_ni.index_r = 0;//需要清理掉文件中的具体数据
            Offline_data_file_clean();}}write_len = sAPI_fwrite(&offline_ni, sizeof(Offline_N), 1,file_hdl);if (write_len != sizeof(Offline_N))        {offline_ni.index_c = old_index_c;offline_ni.all_num = old_all_num;sAPI_fclose(file_hdl);err_code = 2;goto end;}else{//写成功了
        sAPI_fclose(file_hdl);}end:if(err_code == 0){sAPI_Debug("Offline_data_write_num write success");}else{sAPI_Debug("Offline_data_write_num write failed err_code = %d",err_code);}return err_code;
}//读取一次具体的数据
UINT8 Offline_data_read(Offline_D *read_data)
{SCFILE *file_hdl = NULL;UINT8 err_code = 0;long offset = 0;int read_len = 0;//if(read_data == NULL)//{//    err_code = 1;//    goto end;//}if(offline_ni.all_num == 0){//没有数据err_code = 2;goto end;}memset(read_data,0,sizeof(Offline_D));file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_D_PATH,"rb");if(file_hdl == NULL){err_code = 3;goto end;}//找到应该读取的索引offline_ni.index_r = (offline_ni.index_c-offline_ni.all_num+OFFLINE_DATA_SAVE_NUM)%OFFLINE_DATA_SAVE_NUM;offset = offline_ni.index_r*sizeof(Offline_D);sAPI_Debug("Offline_data_read read index_r = %d",offline_ni.index_r);if(sAPI_fseek(file_hdl,offset,FS_SEEK_BEGIN) == 0){sAPI_Debug("Offline_data_read sAPI_fseek success");}else{sAPI_Debug("Offline_data_read sAPI_fseek failed");}read_len = sAPI_fread(read_data,sizeof(Offline_D),1,file_hdl);sAPI_Debug("Offline_data_read read read_len = %d",read_len);if(read_len <= 0){sAPI_fclose(file_hdl);err_code = 4;goto end;}sAPI_fclose(file_hdl);if(Offline_data_write_num(1) != 0){err_code = 5;goto end;}end:if(err_code == 0){sAPI_Debug("Offline_data_read read success");printf_hex(read_data->data, read_data->len);}else{sAPI_Debug("Offline_data_read read failed err_code = %d",err_code);}return err_code;
}void Offline_data_write(UINT8 *data,UINT8 len)
{UINT32 ret = 0;SCFILE* file_hdl = NULL;UINT32 buff_data_len = 0;UINT32 actul_write_len = 0;UINT8 err_code = 0;memset(&offline_data,0,sizeof(Offline_D));offline_data.len = len;memcpy(offline_data.data,data,len);sAPI_Debug("Offline_data_write write data len = %d",len);printf_hex(offline_data.data,len);long offset = 0;file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_D_PATH, "rb+");        //读写模式,可以指定区域指定长度的写if (file_hdl==NULL){err_code = 1;goto end;}sAPI_Debug("_Offline_data_write %s sAPI_fsize %d",OFFLINE_DATA_FILE_D_PATH,sAPI_fsize(file_hdl));//一条数据50字节offset = (offline_ni.index_c%OFFLINE_DATA_SAVE_NUM)*sizeof(Offline_D);sAPI_Debug("Offline_data_write sAPI_fsize %d",sAPI_fsize(file_hdl));sAPI_fseek(file_hdl,offset,FS_SEEK_BEGIN);actul_write_len = sAPI_fwrite (&offline_data,sizeof(Offline_D),1,file_hdl);sAPI_Debug("Offline_data_write write len %d",actul_write_len);if (actul_write_len != sizeof(Offline_D))        {sAPI_fclose(file_hdl);err_code = 2;goto end;}else{//写成功了
        sAPI_fclose(file_hdl);}if(Offline_data_write_num(0) != 0){err_code = 3;goto end;}end:if(err_code == 0){sAPI_Debug("Offline_data_write write success");}else{sAPI_Debug("Offline_data_write write failed err_code = %d",err_code);}
}void Offline_data_file_create(void)
{UINT32 ret = 0;SCFILE* file_hdl = NULL;UINT8 err_code = 0;long offset = 0;file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_D_PATH, "ab+");    if (file_hdl==NULL){err_code = 1;goto end;}sAPI_Debug("Offline_data_file_create %s sAPI_fsize %d",OFFLINE_DATA_FILE_D_PATH,sAPI_fsize(file_hdl));sAPI_fclose(file_hdl);end:if(err_code == 0){sAPI_Debug("Offline_data_file_create success");}else{sAPI_Debug("Offline_data_file_create filed err_code = %d",err_code);}
}//清空文件
void Offline_data_file_clean(void)
{SCFILE* file_hdl = NULL;UINT8 err_code = 0;file_hdl = sAPI_fopen(OFFLINE_DATA_FILE_D_PATH, "w");    if (file_hdl==NULL){err_code = 1;goto end;}sAPI_fclose(file_hdl);end:if(err_code == 0){sAPI_Debug("Offline_data_file_clean success");}else{sAPI_Debug("Offline_data_file_clean filed err_code = %d",err_code);}
}

 


该算法是我在一个项目使用的,需要完成的功能:当设备没有网络时需要保存离线数,恢复网络后再将所有的离线数据上报,中间设备可能会重启,所有在调用方面按照我的项目逻辑进行调用。

使用时应先调用Jtx_Offline_data_file_create(),没有文件时可以创建文件,然后调用Offline_data_get_num()读取文件存储条数已经写入的索引,每次设备开机后都可以知道上一次开机存储总条数和写入索引,方便本次能继续写入或者读取

数据读取:在项目中网络恢复后会一直调用Offline_check_is_data()去检查有没有存储数据,如果有再去调用Offline_data_read(Jtx_Offline_D *read_data)读取数据

数据写入:调用Offline_data_write(UINT8 *data,UINT8 len)

http://www.jsqmd.com/news/6014/

相关文章:

  • redis使用lua脚本迁移数据到集群版redis失败怎么解决
  • 【IEEE-CPS出版】2025年数据管理与计算机科学国际学术会议(ICDMCS 2025)
  • 详细介绍:医疗编程AI技能树与培训技能树报告(国内外一流大学医疗AI相关专业分析2025版,下)
  • 实用指南:Unity单元测试:C语言轻量级框架实战
  • 【ACM出版】第五届管理科学和软件工程国际学术会议(ICMSSE 2025)
  • PiXYZ Studio 2021下载地址与安装教程
  • coremail日常操作
  • Win 10 LSTC 使用 Podman - tfel
  • 深入解析:在 C# .NETCore 中使用 MongoDB(第 2 部分):使用过滤子句检索文档
  • 标签化模板之styled-components原理
  • Halcon基础——图像增强
  • Day24接口的定义与实现
  • 题解:CF2146D2 Max Sum OR (Hard Version)
  • 深入解析:4、urbane-commerce 认证请求 DTO 设计规范
  • 实用指南:基于MATLAB的8QAM调制解调仿真与BER性能分析
  • NVIDIA 开源 Audio2Face:音频生成逼真面部动画;Gemini Live API 支持思考能力 丨日报
  • 【数据结构】冒泡、选择、插入、希尔排序的完成
  • 选对强大的技术底座:一篇文章讲透虚拟机与容器核心差异
  • mp4/图片转gif
  • 详细介绍:09.【Linux系统编程】“文件“读写操作,Linux下一切皆文件!
  • 数据类型-元组
  • 深入解析:招聘:解决方案架构师 - 中国北京(混合办公)
  • 个人用云计算学习笔记 --14( Linux 逻辑卷管理、Linux 交换空间管理) - 教程
  • 自然灾害vr学习机:山体滑坡+泥石流避险+洪涝逃生+地震逃生+台风避险+雷电避险 - 详解
  • 【面板材料】A股上市公司增发股票及配股相关资料(1991-2024年)
  • BindingList的应用与改进
  • 谷歌 SEO 新词 xx animate 等实操教程
  • US$248 Xhorse VVDI2 BMW FEM/BDC + Copy 48 Transponder (96 Bit) + MQB Authorization
  • 完整教程:【读书笔记】架构整洁之道 P6 实现细节
  • Print Conductor打印软件安装教程!一款非常好用的批量打印软件!支持PDF、Word、Excel、图片等