本节主要讨论如何使用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,-