fread是C语言标准库中用于从文件中读取二进制数据的函数,定义在stdio.h头文件中,它可以直接将文件中的二进制内容读取到指定的内存缓冲区中,相比文本读取函数更适合处理非文本类文件。

fread函数的基本语法
fread的函数原型如下:
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
各个参数的含义如下:
- ptr:指向接收读取数据的内存缓冲区的指针,读取的内容会存放到这个地址开始的内存空间中
- size:每个要读取的元素的大小,单位是字节,通常可以用sizeof运算符计算
- nmemb:要读取的元素个数
- stream:指向已经打开的文件的FILE指针,文件需要以二进制读取模式打开,比如rb模式
函数的返回值是实际成功读取的元素个数,如果返回值小于nmemb,可能是到达了文件末尾或者发生了读取错误,可以通过feof或者ferror函数判断具体原因。
fread函数的使用步骤
使用fread读取文件一般遵循以下步骤:
- 包含stdio.h头文件
- 使用fopen函数以二进制读取模式打开目标文件,获取FILE指针
- 定义足够大的缓冲区,用于存储读取到的数据
- 调用fread函数执行读取操作,根据返回值判断读取结果
- 使用完文件后调用fclose函数关闭文件,释放资源
读取普通二进制文件的示例
下面的示例演示了使用fread读取一个二进制文件的内容,并将读取到的字节打印出来:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 以二进制读取模式打开文件
FILE *fp = fopen("test.bin", "rb");
if (fp == NULL) {
printf("文件打开失败n");
return 1;
}
// 定义缓冲区,大小为1024字节
unsigned char buffer[1024];
// 每次读取1个字节,最多读取1024个
size_t read_count = fread(buffer, 1, 1024, fp);
printf("成功读取了%zu个字节n", read_count);
// 打印读取到的内容
for (size_t i = 0; i < read_count; i++) {
printf("%02x ", buffer[i]);
}
printf("n");
// 关闭文件
fclose(fp);
return 0;
}
读取结构体文件的示例
fread非常适合读取存储了结构体数据的二进制文件,下面的示例演示了将结构体数据写入文件后再读取回来的过程:
#include <stdio.h>
#include <string.h>
// 定义结构体
typedef struct {
int id;
char name[20];
float score;
} Student;
int main() {
// 先写入一个结构体数据到文件
FILE *fp_write = fopen("student.bin", "wb");
if (fp_write == NULL) {
printf("写入文件打开失败n");
return 1;
}
Student stu_write = {1, "张三", 95.5};
fwrite(&stu_write, sizeof(Student), 1, fp_write);
fclose(fp_write);
// 读取结构体数据
FILE *fp_read = fopen("student.bin", "rb");
if (fp_read == NULL) {
printf("读取文件打开失败n");
return 1;
}
Student stu_read;
// 读取一个Student大小的元素,读取1个
size_t read_num = fread(&stu_read, sizeof(Student), 1, fp_read);
if (read_num == 1) {
printf("学号:%dn", stu_read.id);
printf("姓名:%sn", stu_read.name);
printf("分数:%.1fn", stu_read.score);
} else {
printf("读取结构体失败n");
}
fclose(fp_read);
return 0;
}
使用fread的注意事项
- 打开文件时必须使用二进制模式,比如rb、rb+,如果使用文本模式r打开,在Windows系统下可能会把换行符转换,导致读取的数据和文件实际内容不一致
- 缓冲区的大小要足够容纳要读取的数据,避免内存溢出,如果不确定文件大小,可以先用fseek和ftell获取文件大小,再分配对应大小的缓冲区
- 不要忽略fread的返回值,返回值小于nmemb时不一定是错误,可能是文件内容已经全部读取完毕,需要结合feof函数判断是否是到达文件末尾
- 读取结构体时要注意内存对齐问题,如果结构体在不同编译器下内存对齐规则不同,可能会导致读取的数据错位,跨平台使用时需要特别注意
常见问题解答
fread和fscanf有什么区别
fread是二进制读取函数,直接读取文件的原始二进制内容,不做任何格式转换,适合所有类型的文件;fscanf是格式化读取函数,按照指定的格式从文本文件中读取内容,会自动转换数据类型,只适合读取文本格式的文件。
为什么fread读取后数据不对
最常见的原因是文件打开模式错误,没有使用二进制模式;其次是缓冲区大小不足,或者size和nmemb参数设置错误,比如把每个元素的大小设成了1,而实际要读取的是结构体,就会导致读取的数据不完整。