一个环形的文件存储算法

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

写入文件按照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.mzph.cn/news/921896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

商业空间设计网站大全中国建设银行卖狗年纪念币官方网站

版权声明&#xff1a;本文为作者原创&#xff0c;如需转载&#xff0c;请注明出处https://blog.csdn.net/weixin_42940826注&#xff1a;以下图片来自于《图解密码学》&#xff0c;这本书讲的更全面细致&#xff0c;建议阅读&#xff0c;在我资源库中有此书&#xff0c;还有使用…

Drools 7.0整合SpringBoot 2.0基础环境搭建

Drools 7.0整合SpringBoot 2.0基础环境搭建一、环境概述 JDK:openjdk version "1.8.0_452" Maven: maven 3.8.8 Drools:Drools 7.73.0.Final SpringBoot:SpringBoot 2.7.18二、项目依赖 这里没有引入drool…

网站建设赚钱吗排版设计是什么工作

基于WebSocket实现的后台服务&#xff0c;用于接收客户端的心跳消息&#xff0c;并根据心跳消息来维护客户端连接。 具体实现中&#xff0c;服务启动后会创建一个HttpListener对象&#xff0c;用于监听客户端的WebSocket连接请求。当客户端连接成功后&#xff0c;服务会为每个…

h5购物网站模板wordpress 整站源码

1. 初识http HTTP 最新的版本应该是 HTTP/3.0&#xff0c;目前大规模使用的版本 HTTP/1.1&#xff1b; 下面来简单说明一下使用 HTTP 协议的场景: 1、浏览器打开网站 (基本上) 2、手机 APP 访问对应的服务器 (大概率) 前面的 TCP与UDP 和http不同&#xff0c;HTTP 的报文格式&a…

超能力联盟网站乐清网站只做

2019独角兽企业重金招聘Python工程师标准>>> property (nonatomic, assign) CGRect prototypeRect; -----这样的声明应该没有问题的&#xff0c;的if(!self.prototypeRect)报错是因为 CGRect是结构体&#xff0c;不能作非nil判断&#xff0c;你可以利用self.protot…

redis使用lua脚本迁移数据到集群版redis失败怎么解决

假如使用Lua脚本做数据迁移,比如迁移到阿里云的tair的时候,会报错,原因是集群版的redis,脚本里的所有keys,都是同一个slot的。但是redis的slot有16384个,很难保证插入的数据是同一个slot。假如分开不同的slot来插…

【IEEE-CPS出版】2025年数据管理与计算机科学国际学术会议(ICDMCS 2025)

2025年数据管理、计算机科学国际学术会议(ICDMCS 2025),将于2025年10月24-26日在中国江苏省南京市召开。【高录用快见刊、检索:合作IEEE-CPS出版社审稿录用速度快,最快投稿后2-4个月左右见刊,见刊后1个月左右EI、S…

详细介绍:医疗编程AI技能树与培训技能树报告(国内外一流大学医疗AI相关专业分析2025版,下)

详细介绍:医疗编程AI技能树与培训技能树报告(国内外一流大学医疗AI相关专业分析2025版,下)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !imp…

实用指南:Unity单元测试:C语言轻量级框架实战

实用指南:Unity单元测试:C语言轻量级框架实战pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

做网站可能遇到的困难做站群的网站要备案吗

1查看数据情况 df.shape df.info() 2.用指定值填充 df df.fillna(x) 3.判断是否缺失 df.isnull() 4.删除缺失数据 df df.dropna() 5.补充平均值 df df.fillna(df.mean()) 6.填充他前面一个元素值(ffill向前填充&#xff0c;bfill向后填充)&#xff08;limit:可以…

网站上不去首页seo要怎么办wordpress 补丁

基本介绍 Java Agent是一种特殊的Java程序&#xff0c;它允许开发者在Java虚拟机(JVM)启动时或运行期间通过java.lang.instrument包提供的Java标准接口进行代码插桩&#xff0c;从而实现在Java应用程序类加载和运行期间动态修改已加载或者未加载的类&#xff0c;包括类的属性、…

免费的网站域名商业网站案例

基于Docker for Windows部署ChatGPT-Next-Web 项目地址安装Docker for Windows部署项目参数讲解参数示例 运行 项目地址 https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web 安装Docker for Windows 官网地址&#xff1a;https://www.docker.com/ 下拉找到Download 选择W…

【ACM出版】第五届管理科学和软件工程国际学术会议(ICMSSE 2025)

第五届管理科学和软件工程国际学术会议(ICMSSE 2025)将于2025年10月24-26日于南京召开。【高届数、范围广、录用高、见刊快、检索稳】 【管理科学、软件工程、计算机相关主题方向均可投稿】 第五届管理科学和软件工程国…

PiXYZ Studio 2021下载地址与安装教程

软件介绍 PiXYZ Studio 2021是Unity公司推出的专业3D数据准备与优化工具,专为处理复杂CAD、3D和点云模型设计。该版本通过集成自动化批处理、实时协作与跨平台兼容功能,显著提升工业设计与实时3D开发的效率。其核心功…

coremail日常操作

客户端下载: https://www-lunkr.coremail.cn/download.html#email 创建测试用户: 登录webadmin,点组织管理-用户管理,新建用户

很多网站开发没有框架如何制作的如何 做网站挣钱

wow代码人们让钱包瑟瑟发抖的双十一已经来啦与此同时码不停蹄地向你奔赴而来的还有 CSDN 为你准备的???? 1 元秒杀 ????价值 3.5 万元的爆款电子书限时特惠&#xff0c;仅需 1 元你&#xff0c;准备好了吗仅限 1000 人速领????????????错过悔10年系列好书

Win 10 LSTC 使用 Podman - tfel

小记一下 Win 10 LTSC 上运行 WSL, Podman 相关的知识前言全文仅为个人折腾记录因为需要跑 docker,发现自己的电脑上还没有装。加上先前在网上看到有人对比 Docker 和 Podman以及之前自己使用 Colima 的记忆, 决定用 …

深入解析:在 C# .NETCore 中使用 MongoDB(第 2 部分):使用过滤子句检索文档

深入解析:在 C# .NETCore 中使用 MongoDB(第 2 部分):使用过滤子句检索文档2025-09-29 14:03 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflo…

网站开发知乎wordpress进入

如图所示&#xff0c;在公式后面加编码后公式也变小了&#xff1a; 加编码前&#xff1a; 加编码后&#xff1a; 采用样式分隔符&#xff08;Ctrlaltenter&#xff09;即可解决&#xff0c;输完公式后&#xff0c;按enter转行&#xff0c;输入你要的东西&#xff08;编号什么的…

电脑和手机都能浏览的网站开发网站开发后端需要哪些技术

来源 | 扔物线责编 | Carol文章开始之前&#xff0c;首先来看个视频&#xff1a;开始说到依赖注入&#xff0c;做 Android 的人都会想到一个库&#xff1a;Dagger&#xff1b;说到 Dagger&#xff0c;大家的反应普遍是一套三连&#xff1a;牛逼、高端、我才不用。又牛逼又高端&…