本节主要讨论如何使用C语言随机读写二进制文件。

本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频

文件既可以顺序读写,也可以随机读写。所谓顺序读写,可以简单理解为从头读/写到尾,数据项是一个接着一个进行读取/写入的;而随机读写则允许我们随时改变文件的当前读写位置,如果在非文件尾的位置写入内容,则相应位置的原始数据会被覆盖。

二进制文件可以视为字节流,程序为每一个被打开的二进制文件维护了一个读写位置标记,该标记为一个整数,表示当前读写位置相对于文件起始处的偏移量,以字节为单位。随着文件读写操作的进行,该读写位置会自动后移,其偏移量等于读写操作的字节数。

表20-6 文件随机访问函数(C语言)

函数 说明
rewind void rewind(FILE* f);说明:将文件f的读写位置移回文件头(起始处)。
fseek int fseek(FILE* f, long offset, int origin);说明:该函数通常应用于二进制文件,其将文件f的读写位置移动至偏离参考点(origin)指定偏移量(offset)的位置。参考点origin应为SEEK_SET、SEEK_CUR、SEEK_END之一,依次为文件头、当前读写位置和文件尾。函数应用于文本文件时,offset只能是0或者是前次ftell()的返回值,而origin只能是SEEK_SET。操作成功,函数返回0,否则返回非零值。
ftell long ftell(FILE* f);说明:对于二进制文件,返回文件的当前读写位置,即当前读写位置相对于文件头的偏移字节数。对于文本文件,函数返回值可能没有实际意义,但仍然可以配合fseek()函数恢复文件的读写位置。如果函数执行出错,返回-1。
fgetpos int fgetpos(FILE* f, fpos_t* pos);说明:获取文件f的当前读写位置,写入指针pos所指向的fpos_t对象中。指针pos指向的对象必须是已分配好的。通常情况下,fpos_t事实上是长整型或者长长整型。操作成功,函数返回0,否则返回非零值。
fsetpos int fsetpos(FILE* f, const fpos_t* pos);说明:设置文件f的读写位置,指针pos所指向的fpos_t对象即为目标位置。操作成功,函数返回0,否则返回非零值。

表20-6列出了C语言中用于二进制文件随机访问的常用函数,以这些函数为工具,我们可以在文件中随意移动读写位置,方便地读写二进制文件。

C语言程序BinaryPriceList展示了一个灵活的二进制商品价格表存储结构,该结构以不重复的固定的商品编号为基础进行工作。

//Project - BinaryPriceList
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <fcntl.h>typedef struct {int iNo;            //商品编号,不重复char sName[20];     //名称float fPrice;       //价格int iQuantity;      //在库数量
} Commodity;bool locateCommodity(FILE* f, int iNo){rewind(f);          //读写指针回到文件头int t;while (true){if (fread(&t,sizeof(int),1,f)!=1)return false;if (t==iNo){fseek(f,-sizeof(int),SEEK_CUR);return true;}elsefseek(f,sizeof(int)+sizeof(float)+20,SEEK_CUR);}
}void saveCommodity(FILE* f, const Commodity* c){if (!locateCommodity(f,c->iNo))fseek(f,0,SEEK_END);fwrite(&c->iNo,sizeof(int),1,f);fwrite(c->sName,20,1,f);fwrite(&c->fPrice,sizeof(float),1,f);fwrite(&c->iQuantity,sizeof(int),1,f);
}bool loadCommodity(FILE* f, int iNo, Commodity* c){if (!locateCommodity(f,iNo))return false;fread(&c->iNo,sizeof(int),1,f);fread(c->sName,20,1,f);fread(&c->fPrice,sizeof(float),1,f);fread(&c->iQuantity,sizeof(int),1,f);return true;
}int main() {char sPath[512];if (getcwd(sPath,512)!=NULL)              //获取并打印当前工作路径printf("cwd: %s\n",sPath);FILE* f = NULL;if (access("commodity.dat",F_OK)==0)     //判断文件是否存在f = fopen("commodity.dat","rb+");     //打开已有文件进行随机读写elsef = fopen("commodity.dat","wb+");     //打开新文件进行随机读写Commodity c1 = {1,"Apple",5.2764123f,2000};saveCommodity(f,&c1);printf("ftell(f): %ld\n",ftell(f));      //输出文件当前读写位置Commodity c3 = {3,"Beef",65.741f,5000};saveCommodity(f,&c3);Commodity c5 = {5,"Cherry",117.4f,500};saveCommodity(f,&c5);strcpy(c3.sName,"Pork");saveCommodity(f,&c3);Commodity t;printf("%-6s%-20s%10s%10s\n","No","Name","Price","Quantity");printf("----------------------------------------------\n");for (int i=1;i<=5;i++){if (!loadCommodity(f,i,&t))printf("%-6d%-20s%10.2f%10d\n",i,"NA",0.0,0);elseprintf("%-6d%-20s%10.2f%10d\n",t.iNo,t.sName,t.fPrice,t.iQuantity);}fclose(f);return 0;
}

上述代码的执行结果为:

cwd: D:\C2Cpp\C20_FileIO\build-BinaryPriceList-Desktop_Qt_5_14_1_MinGW_64_bit-Debug
ftell(f): 32
No    Name                     Price  Quantity
----------------------------------------------
1     Apple                     5.28      2000
2     NA                        0.00         0
3     Pork                     65.74      5000
4     NA                        0.00         0
5     Cherry                  117.40       500

上述程序执行完成后,我们得到一个二进制文件commodity.dat,其尺寸为96字节。为了便于描述上述程序的随机读写过程及工作原理,我们画出了commodity.dat的内部结构,请见图20-7。请读者注意,图20-7只是一个示意图,其并不能“精细”表达commodity.dat的内部结构。

用C语言随机读写二进制文件相关推荐

  1. c语言随机读写信息fetch,北京大学信息科学技术学院考试试卷-计算机系统导论-期中-2015(16页)-原创力文档...

    PAGE 7 ICS 2015 期中试题 第一题 单项选择题(每小题1分,共20分) 给定一个实数,会因为该实数表示成单精度浮点数而发生误差.不考虑NaN和Inf的情况,该绝对误差的最大值为: A. ...

  2. c语言tcp读写二进制文件,通过TCP/IP连接发送二进制文件

    Remy Lebeau.. 13 您需要循环发送和接收.既不保证send()也不recv()保证发送/读取您请求的字节数. 您还应该在文件数据之前发送文件大小,以便接收方知道预期的字节数和停止读取的时 ...

  3. C语言文件读写(3)-二进制文件读写操作

    C语言文件读写-二进制文件读写操作 先说说什么是二进制文件,二进制文件是相对于文本文件而言的,文本文件是由一行一行的字符的有序序列组成的.二进制文件就没有行的概念了,也是由有序的字符组成的,但是在写入 ...

  4. 一种C#读写二进制文件的通用方法

    在日常的工作中,我们经常需要进行一些二进制文件或协议的读写操作,用C#解析二进制文件常常是一件比较麻烦且容易出错的工作,本文介绍了一种在C#中实现快速读写二进制文件通用的方法. 以一个解析Mp3 ID ...

  5. C++实现对象序列化和反序列化(读写二进制文件)操作

    相关函数介绍 在我们的C语言中读写二进制文件一般使用的fread.fwrite全局函数,当然也可以使用更底层的read和write函数.在我们的C++中 通过ofstream 和 ifstream 对 ...

  6. c语言生成随机坐标,C语言 文件的随机读写详解及示例代码

    前面介绍的文件读写函数都是顺序读写,即读写文件只能从头开始,依次读写各个数据.但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写.这种读写方式称为随机读 ...

  7. c语言生成随机的坐标,C语言文件的随机读写

    前面介绍的文件读写函数都是顺序读写,即读写文件只能从头开始,依次读写各个数据.但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写.这种读写方式称为随机读 ...

  8. c语言fseek128字节,C语言rewind和fseek函数的用法详解(随机读写文件)

    前面介绍的文件读写函数都是顺序读写,即读写文件只能从头开始,依次读写各个数据.但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写.这种读写方式称为随机读 ...

  9. C语言文件的随机读写

    C语言文件的随机读写 文件顺序读写,即读写文件只能从头开始,依次读写各个数据.但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写.这种读写方式称为随机读 ...

最新文章

  1. 2022-2028年中国无溶剂聚氨酯复膜胶行业市场调查研究及发展前景规划报告
  2. svn没有右键菜单的解决方案
  3. OpenCV2.4.X怎样使开发出来的exe文件或软件可独立运行?
  4. abp core版本添加额外应用层
  5. redhat搭建php环境,rhel5搭建PHP5.2.6+apache2.2.9开发环境(模块全)
  6. MPU和CPU有什么区别?
  7. HangFire循环作业中作业因执行时间太长未完成新作业开启导致重复数据的问题...
  8. 来之不易的美团面试,结果居然挂了...(附面试答案)
  9. C++ 深拷贝与浅拷贝
  10. HDOJ 1002 A + B Problem II 解题报告
  11. crm客户管理系统源码_公司crm客户关系管理系统的功能
  12. 通过创建一个位图的XY Chart来学习Android绘图类Rect,Paint,Bitmap,Canvas(附源码)
  13. android录制屏幕接口,ARDC Android 远程桌面助手 录屏 演示 MD
  14. 魔兽世界地图插件制作代码
  15. autoCAD绘制简单三维立体图形
  16. maven 中使用jdt编译代码
  17. 单片机定时器实现的数字时钟
  18. 云计算基础与应用 第八章 云安全
  19. BZOJ1695 : [Usaco2007 Demo]Walk the Talk
  20. Cisco综合配置实验——二层、三层交换机、路由器

热门文章

  1. THUWC2018咸鱼记
  2. 计算机火影忍者的谱子,火影忍者动漫曲谱大全
  3. 火影忍者手游修复服务器,火影忍者手游大版本更新异常 问题修复和补偿
  4. 基于JavaEE的服装销售管理系统_JSP网站设计_SqlServer数据库设计
  5. 美创数据安全服务能力再获认可!
  6. 基于大疆无人机SDK二次开发
  7. Tars和Dcache使用中的问题及注意事项
  8. 去打印店打印资料一般需要准备什么,哪里打印程序简便
  9. 【转载】Deep Learning(深度学习)学习笔记整理系列
  10. 数值优化(Numerical Optimization)学习系列-惩罚和增广拉格朗日方法(Augmented Lagrangian Methods)