二进制读写
fread 和 fwrite 以二进制方式读写数据块,不进行任何格式转换。二进制 I/O 适合保存结构体、数组等内存数据的直接映像,效率高且精确,但文件不可人工阅读,且存在字节序和结构体填充的可移植性问题。
fwrite
struct Data {
int id;
double value;
};
struct Data d = {42, 3.14};
FILE *fp = fopen("data.bin", "wb");
if (fp != NULL) {
size_t written = fwrite(&d, sizeof(d), 1, fp);
if (written != 1) {
perror("fwrite");
}
fclose(fp);
}
fread
struct Data d;
FILE *fp = fopen("data.bin", "rb");
if (fp != NULL) {
size_t read = fread(&d, sizeof(d), 1, fp);
if (read == 1) {
printf("id=%d, value=%f\n", d.id, d.value);
} else if (feof(fp)) {
printf("End of file\n");
} else {
perror("fread");
}
fclose(fp);
}
读写数组
int arr[100];
/* 写入 */
FILE *fp = fopen("arr.bin", "wb");
fwrite(arr, sizeof(int), 100, fp);
fclose(fp);
/* 读取 */
FILE *fp2 = fopen("arr.bin", "rb");
fread(arr, sizeof(int), 100, fp2);
fclose(fp2);
可移植性问题
/* 问题 1:字节序 */
/* 小端机器写入,大端机器读取 → 数据错误 */
/* 问题 2:结构体填充 */
struct Example {
char c;
int i; /* 可能有 3 字节填充 */
};
/* 不同编译器填充不同 */
/* 解决方案:逐字段写入 */
fwrite(&d.id, sizeof(int), 1, fp);
fwrite(&d.value, sizeof(double), 1, fp);
常见错误
用文本模式打开:
FILE *fp = fopen("data.bin", "w"); /* 错误:文本模式 */
/* Windows 下会转换 \n → \r\n */
/* 正确 */
FILE *fp = fopen("data.bin", "wb");
不检查返回值:
fread(&d, sizeof(d), 1, fp); /* 可能只读了一半 */
/* 正确 */
if (fread(&d, sizeof(d), 1, fp) != 1) {
/* 处理错误 */
}
最佳实践
- 二进制文件用
"b"模式 - 检查
fread/fwrite返回值 - 考虑字节序问题(跨平台时)
- 结构体序列化时逐字段写入
- 文件头包含版本和大小信息