如何做bin文件升级以及数据定位——文件操作函数簇!

简介: 如何做bin文件升级以及数据定位——文件操作函数簇!

写在前面

之前自己一直在做芯片上应用程序的升级功能,也就是所谓的Bootloader程序,当然,是Secondery Bootloader程序。

在做芯片升级的BootLoader程序时,我的做法计较简单:一般是接收上位机下发的数据,判断数据协议是否正确,判断正确后将数据写入flash。可是,上位机是如何把数据打包发来的,如何按协议组数据帧,如何在一个bin文件中准确定位数据,自己却一致没有机会接触。

偶然的机会需要在掌机上开发对芯片进行升级的功能,由于下位机代码是自己已经写好的BootLoader程序,协议什么的还算是比较熟悉,便就着这个机会接触到了文件操作函数。

本文包含

  1. 文件指针及文件信息结构
  2. 文件打开
  3. 文件关闭
  4. 文件中数据定位
  5. 文件删除
  6. 文件列表菜单显示

文件指针及结构体定义

c语言库中包含了许多对文件操作的函数库,其中对文件指针的定义为

_FILE *FilePointer

_FILE 由c语言库定义好,我们可以直接定义文件指针,用来保存我们需要操作的文件信息。

文件指针是什么?通俗点讲,我们打开一个文件时,需要一个指针指向该文件,但该指针的类型是FILE型的,不恰当的理解可以为指向的是文件名,当然实际上该指针信息包含的不止文件名。

另一个需要定义的是保存查找到的文件信息的结构体,如下:

typedef __packed struct FINDBLK{
    U16 num;     // 查找到的文件个数
    U8 Cur_S; 
    U8 Index;    
    S8 name[8];  // 文件名,支持8字节长度,可更改
    S8 ext[3];
    S8 dir[65];  // 路径
    U8 ff_ftime[16];   /* file  date_time*/
    U32 ff_fsize;       /* file size */
    S8 ff_name[13];     /* found file name */
    U8 ff_attrib;       /* attribute found */
}FindBlk;

通过上面的结构体,可以定义一个查找到的文件信息的变量,用来进行文件操作。

文件查找

定义完结构体之后,需要去查找并打开文件,用到 findfirst 和 findnext函数,这两个函数功能如其名。

注意: 在打开文件之前需要把文件关闭,断开文件指针与文件的关系后,重新建立联系。

下面是定义一个文件信息并查找打开文件。

    FindBlk fileinfo;
    U8 ret;
    
    LCDcls();     //清屏
    _fcloseall();//查找打开文件之前关闭所有文件
    _setcurdir("D:\\"); //设置查找文件的目录
    ret = _findfirst("*.bin",&fileinfo);
    // 查找bin文件,用通配符*代替文件名
    line = 3;
    num = 0;
    while(ret==0)
    {
        strncpy(&name[num][0],&fileinfo.ff_name,sizeof(fileinfo.ff_name));
        ret = _findnext(&fileinfo);
        num++;// 个数计数器
    }

    if (num == 0)
    {
        while (1)
        {
            myPutString(4,1,"无文件",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                return;
            }
        }
    }    
... ...

上面代码主要是将符合bin格式的文件查找到,并将文件名保存到定义好的name数组中,并用计数器num记录查找到的文件个数。

文件打开与数据定位

查找到文件后,需要打开该文件,也就是重新建立文件指针与文件的关系。通过索引出需要打开的文件的文件名,利用fopen 、 fseek 、filelength 和 fread 函数定位数据。

LCDcls();
    _fclose(FilePointer);
    FilePointer = _fopen(&name[cn-1][0],"r"); //传入文件名,返回文件指针。

    if (FilePointer != 0)
    //此处不规范,规范为 != NULL ((void *) 0)
    {
        filesize = _filelength(FilePointer); 
        // 传入文件指针,返回该文件的文件长度,字节数。
        filesize_ori = filesize;
        _fseek(FilePointer,0,0);
        // 首先将文件指针定位到 文件的起始位置,起始0偏移0
        memset(data_buffer,0,sizeof(data_buffer));
        //数据缓存区清零
        _fread(data_buffer,filesize,FilePointer);
        // 将文件中的数据读取保存到缓冲区中
        // filesize--需要读取的长度 FilePointer--文件指针
    // 注:每次读取之后,文件指针会自动偏移到读取完的字节后,如读取1024个字节(0-1023),读取后文件指针会指向第1025个字节,即索引为1024的字节。
        memset(&data_buffer[filesize],0x1A,(1024*(filesize/1024+1) - filesize));

        if (filesize % 1024 != 0)
        {
            filesize = 1024*(filesize/1024+1);
        }
        ChooseFile_flag = 1;
        
        while (1) 
        {    
            myPutString(4,1,"打开成功",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                break;
            }
        }
    }    
    else
    {
        ChooseFile_flag = 0;
        while (1)
        {
            myPutString(4,1,"打开失败",1);
            myPutString(4,2,"按确认返回",1);
            if (_bioskey(0) == ENTER)
            {
                LCDcls();
                break;
            }
        }
    }

通过以上操作便完成了文件的打开以及数据的定位读取。

文件删除

文件删除很简单,调用_filedelete即可。

    do
    {
        ret = _filedelete(&name[cn-1][0]);
    }while(ret != 0);

    LCDcls();

    num--;

_filedelete 传入的是需要删除的文件名,返回为结果0或1,当然,在做删除之前需要关闭文件并设置路径。

    _fcloseall();   /* 必须先关闭所有文件 */
    _setcurdir("D:\\");

一个屏幕显示多文件的小程序

LOOP9:while(1)
    {    
        myPutString(4,1,"--选择删除--",1);
        _setdispcolor(1);


        if((k!=0)||(fist==0))/* 有按键按下 或第一次执行 */
        {
            for(i = 0;i < num;i++)
            { 
                if(i == (cn-head))
                {
                    myPutString(4,3+i,&name[cn-1][0],0);
                }
                else
                {
                    myPutString(4,3+i,&name[i+head-1][0],1);
                }
                if ((i>=7)||(i>=num))
                {
                    break;
                }
            }
            fist = 1;
            k = 0;
        }
                    
        k = _key_time(100);
    
        if(k==DOWN)
        {
            cn++;
            if (cn > tail) 
            {
                head++;
                tail++;
            }
            Oper_flag = 1;
        }            
        if(k==UP)
        {
            cn--;
            if (cn < head)
            {
                head--;
                tail--;
            }
            Oper_flag = 1;
        }        
        if(k==ENTER)
        {
            res = DeleteInfirm();

            if (res == 0)
            {
                break;
            }
            else
            {
                LCDcls();
                goto LOOP9;
            }    
        }
        if(k==ESC)
        {
            LCDcls();
            return;
        }
        if(cn <= 0)
        {
            cn = num;
            if (num>7)
            {
                head = num-6;
                tail = num;
            }
            else
            {
                head = 1;
                tail = 7;
            }
        }                
        if(cn > num)
        {
            cn = 1;
            head = 1;
            tail = 7;
        }
    }

该程序实现的是在掌机上显示查到的文件名,以列表的形式显示出来。由于屏幕大小的限制,同一屏幕最多显示7个文件,如果文件多余7个,我们需要按上下键来实现文件名的刷新上下移动。这个小程序就是实现这个功能的。

相关文章
|
7月前
|
Windows
(文件[夹]批量分类整理_多级匹配_交叉匹配_路径结构交叉调整)文件[夹]批量复制
该文介绍了如何使用特定工具进行批量文件整理。首先,需要从提供的百度网盘和蓝奏云链接下载工具,并用提取码解锁。接着,打开工具的批量复制功能,将待整理的图片文件拖入“来源路径”,目标文件夹拖入“终点路径”。通过层级过滤排除不需要的路径。然后,利用多级匹配设置,提取文件名和路径中的关键词,如“动物”、“小型”、“食草”等,设置复制后的文件重命名规则。最后,执行批量复制,完成文件的智能分类与命名。整个过程旨在根据文件的原始分类信息,自动将其移动到相应的新目录结构下。
|
Linux 测试技术 数据处理
R语言丨根据VCF文件设计引物,自动识别两样本差异SNP位点,调用samtools获取上下游参考序列,快速得到引物序列
R语言丨根据VCF文件设计引物,自动识别两样本差异SNP位点,调用samtools获取上下游参考序列,快速得到引物序列
|
存储 缓存 安全
Linux中最低调、最易让人忽视的tmp目录,原来用处那么大!
Linux中最低调、最易让人忽视的tmp目录,原来用处那么大!
1371 0
|
存储 Windows
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(二)
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(二)
286 0
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(二)
|
存储 Windows
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(一)
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(一)
422 0
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★(一)
|
Shell Linux
如何高效回退到特定层级目录?
这个脚本在经常需要切换目录,并且路径又很长的情况下,非常有用,能够快速进入到你想要的父目录。好好使用这个脚本,将会在目录切换时大大提高你的效率。
176 0
|
数据可视化 数据挖掘
差异分析③
统计差异基因数目 tfit
1125 0
|
API 数据安全/隐私保护 网络架构
Confluence 6 目录序列将会影响
这个部分将会对用户目录序列对登录和权限以及更新用户和用户组的影响进行描述。 登录 用户目录的排序在用户登录系统中的影响是非常重要的,尤其对一个相同用户名的用户在多个目录中存在的情况。
935 0