二进制文件
1.其实所有的文件最终都是二进制的
文本文件无非是用最简单的方式可以读写的文件
more、tail
cat
vi
而二进制文件是需要专门的程序来读写的文件
文本文件的输入输出是格式化,可能经过转码
2.文本VS二进制
Unix喜欢用文本文件来做数据存储和程序配置
交互式终端的出现使得人们喜欢用文本和计算机talk
Unix的shell提供了一些读写文本的小程序
Windows喜欢用二进制文件
DOS是草根文化,并不继承和熟悉Unix文化
PC土豪的西牛能力有限,DOS的能力钢有限,二进制更接近底层
文本的优势是方便人类读写,而且跨平台
文本的缺点是程序输入输出要经过格式化,开销大
二进制的缺点是人类读写困难,而且不跨平台:int的大小不一致,大小端的问题……
二进制的优点是程序读写快
3.程序为什么要文件?
配置:Unix用文本,Windows用注册表
数据:稍微有点量的数据都放数据库了
媒体:这个只能是二进制的
现实是,程序通过第三方库来读写文件,很少直接读写二进制文件了
4.二进制读写
size_t fread(void *restrict ptr,size_t size,size_t nitems,FILE *restrict stream);
size_t fwrite(const void *restrict ptr,size_t size,size_t nitems,FILE *restrict stream);
注意FILE指针是最后一个参数
返回的是成功读写的字节数
5.为什么nitem?
因为二进制文件的读写一般都是通过对一个结构变量的操作来进行的
于是nitem就是用来说明这次读写几个结构变量
代码:
在main.c中:
在student.h中:
#ifndef _STUDENT_H_#define _STUDENT_H_const int STR_LEN=20;//typedef struct _student{ //声明了一个结构类型,叫student char name[20]; //字符数组,大小20 int gender; int age;}Student;#endif // _STUDENT_H_6.在文件中定位
知道现在处在文件的什么位置上,也可以直接跑到文件的某个地方去
long ftell(FILE *stream);
int fseek(FILE *stream,long offset,nt whence);
SEEK_SET:从头开始
SEEK_CUR:从当前位置开始
SEEK_END:从尾开始(倒过来)
在main.c中:
#include "student.h"void read(FILE *fp,int index);int main(int argc,char const *argv[]){ FILE *fp=fopen("main.c","r");//打开来读 if(fp){//打开成功 fseek(fp,0L,SEEK_END); //fseek表示要把我读写的位置移到什么地方去,SEEK_END表示从尾巴开始往前,倒过来算,0L倒过来算0, //这句运行完,当前位置就在尾巴上了 long size=ftell(fp);//ftell得到现在所在的位置,移到最尾巴上,这个尾巴的位置其实表达的是这个文件的大小 int number=size/sizeof(Student);//得到有几个这样的结构 int index=0; printf("有%d个数据,你要看第几个:",number); scanf("%d",&index); read(fp,index-1);//第0个,人类的第一个-1,把index-1交给read函数 fclose(fp); } return 0;}void read(FILE *fp,int index)//read函数得到 文件得到文件指针,得到index{ fseek(fp,index *sizeof(Student),SEEK_SET); //从SEEK_SET文件的头开始,往前走到sizeof(Student)这个位置, Student stu; if(fread(&stu,sizeof(Student),1,fp)==1){//读这个位置上的结构,读1个结构 printf("第%d个学生:n",index+1); printf("t姓名:%sn",stu.name); printf("性别:"); switch(stu.gender){ case 0:printf("男n");break; case 1:printf("女n");break; case 2:printf("其他n");break; } printf("t年龄:%dn",stu.age); }}7.可移植性
这样的二进制文件不具有可移植性
在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出
解决方案之一是放弃使用int,二是typedef具有明确大小的类型
更好的方案是用文本