上一篇主要讲了文件文本形式的读写函数以及文件的关闭与打开,详情参考C语言 文件操作(一)。接下来主要介绍文件的二进制形式的读写以及文件指针定位等。
二进制形式的读写
二进制文件不是以ASCII代码存放数据的,它将内存中数据存储形式不加转换地传送到磁盘文件,因此它又称为内存数据的映像文件。因为文件中的信息不是字符数据,而是字节中的二进制形式的信息,因此它又称为字节文件。
对二进制文件的操作也需要先打开文件,用完后要关闭文件。二进制文件除了可以作为输入文件或输出文件外,还可以是既能输入又能输出的文件。这是和ASCII文件不同的地方。
fwrite()函数
调用格式:size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream)
;
功能:把数据的二进制写入到文件中。
参数说明:
ptr:要写入的数据的首地址
size:写入的字节数
nmemb:写入的次数
stream:文件指针,fopen的返回值
返回值:成功写入的次数
fread()函数
调用格式:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
;
功能:从文件中以二进制的形式读取数据到内存中
参数说明:
ptr:读取数据后的存储位置
size:每次读取的字节数
nmemb:读取的次数
stream:文件指针,fopen的返回值
返回值:实际读取数据块的个数
从stu.dat文件中读取数据到学生结构变量中,并显示结构变量中的内容。
#include <stdio.h>
typedef struct Student
{
char name[20];
int id;
short age;
}Student;
int main()
{
FILE* fwp = fopen("stu.dat","wb+");
Student stu = {"xixi",10086,28};
int ret = fwrite(&stu,1,sizeof(Student),fwp);
// 把文件位置指针调整到开头
rewind(fwp);
Student stu1 = {};
fread(&stu1,1,sizeof(Student),fwp);
printf("%s %d %hd\n",stu1.name,stu1.id,stu1.age);
}
运行结果:
$ ./a.out
xixi 10086 28
文件流之文件的定位
文件的随机读写有时用户想直接读取文件中间某处的信息, 若用文件的顺序读写必须从文件头开始直到要求的文件位置再读, 这显然不方便。C语言标准库提供了一组文件的随机读写函数, 即可以将文件位置指针定位在所要求读写的地方直接读写。
使用"w"、"r"打开的文件位置指针都在文件的开头,而使用"a"打开的文件,位置指针都在末尾。
位置指针会随着数据的读写而变化。
fseek()函数
调用格式:int fseek(FILE *stream, long offset, int whence)
;
功能:设置文件的位置指针,位置指针会设置到 基础位置+偏移值
参数说明:
stream:文件指针
offset:偏移值
whence:基础位置
常量 | 描述 |
---|---|
SEEK_SET | 文件的开头,offset必须是一个非负值 |
SEEK_CUR | 文件指针的当前位置,offset可正可负 |
SEEK_END | 文件末尾,offset可正可负,如果是正直将定位到文件尾的后面 |
ftell()函数
调用格式:long ftell(FILE *stream)
;
功能:获取文件的位置指针,位置指针当前所在的字节数
rewind()函数
调用格式:void rewind(FILE *stream)
;
功能:把文件的位置指针,调整到开头。
实现一个函数,计算文件的大小。
#include <stdio.h>
size_t file_size(const char* path)
{
FILE* frp = fopen(path,"r");
if(NULL == frp)
{
perror("fopen");
return 0;
}
// 调整文件位置指针到末尾
fseek(frp,0,SEEK_END);
return ftell(frp);
}
int main()
{
printf("%d\n",file_size("day03.zip"));
}
注意:
当数据写入后并没有立即同步到磁盘中,而存储在缓冲区中,只有满足以下条件时才会从缓冲区中写入到磁盘中。
1、从输出调整到输入。
2、缓冲区满4k
3、文件关闭
4、程序结束
5、手动刷新 fflush()函数;
调用格式:int fflush(FILE *stream)
;
功能:该函数将输出缓冲区的内容实际写入文件中, 而将输入缓冲区的内容清除掉
其他函数
feof()函数
调用格式:int feof(FILE *fp)
;
功能:该函数用来判断文件是否结束
返回值
0:假值,表示文件未结束。
1:真值,表示文件结束。
这个函数对二进制文件操作特别有用, 因为二进制文件中,文件结尾标志 EOF 也是一个合法的二进制数,只简单的检查读入字符的值来判断文件是否结束是不行的。如果那样的话, 可能会造成文件未结尾而被认为结尾, 所以就必须有 feof()函数。
下面的这条语句是常用的判断文件是否结束的方法。
while(!feof(fp))
fgetc(fp);
ferror()函数
调用格式:int ferror(FILE *fp)
;
功能:检查由fp指定的文件在读写时是否出错
返回值:
0:假值,表示无错误。
1:真值,表示出错。
#include <stdio.h>
int main()
{
FILE* frp = fopen("test.txt","r");
if(NULL == frp)
{
perror("fopen");
return -1;
}
int num = 0;
float f = 0;
char ch = 0;
int ret = fscanf(frp,"%d %f %hhd",&num,&f,&ch);
printf("%d %f %c %d\n",num,f,ch,ret);
}
clearerr()函数
调用格式:void clearerr(FILE *fp)
;
功能:清除由fp指定文件的错误标志。
exit()函数
调用格式:void exit(int status)
;
功能:exit()函数使程序立即终止执行,同时将缓冲区中剩余的数据输出并关闭所有已经打开的文件。
status:为0值表示程序正常终止,为非0值表示一个定义错误。