为何fwrite()已将结构体数组写入文件,fread()却无法读取内容?
结构体数组读写文件后fread无输出?这锅文件指针背定了!
兄弟,你猜的方向完全正确——fwrite之后文件指针停在末尾就是导致你读不到数据的罪魁祸首!当你把结构体数组写完,文件内部的位置指针已经跑到文件最后了,这时候直接调用fread,自然啥也读不到,因为后面根本没数据了。
下面给你把问题拆解清楚,再附上可运行的修复代码:
为啥会出现这问题?
当fwrite()执行完成后,文件的位置指针会指向写入内容的末尾。打个比方,你把书翻到最后一页了,再往下翻当然是空的,fread就是这个道理,从当前指针位置开始读,自然返回0,读不到任何有效数据。
两种简单修复方法
方法1:写完后把指针掰回开头
在fwrite()之后、fread()之前,用fseek()把文件指针移回文件起始位置就行,代码示例给你补全了:
#include <stdio.h> #include <string.h> #include <stdlib.h> struct NOVEL { char title[50]; char newtitle[50]; char author[50]; }; int main() { // 初始化测试用的结构体数组 struct NOVEL books[2] = { {"The Old Man and the Sea", "老人与海", "Ernest Hemingway"}, {"1984", "一九八四", "George Orwell"} }; struct NOVEL read_books[2]; // 用来存读取的数据 FILE *fp = fopen("novels.dat", "wb+"); // 用wb+模式,支持读写二进制 if (!fp) { perror("打开文件失败"); return 1; } // 写入结构体数组 size_t write_num = fwrite(books, sizeof(struct NOVEL), 2, fp); printf("成功写入%zu个结构体\n", write_num); // 关键操作:把文件指针移到文件开头 if (fseek(fp, 0, SEEK_SET) != 0) { perror("移动文件指针失败"); fclose(fp); return 1; } // 读取结构体数组 size_t read_num = fread(read_books, sizeof(struct NOVEL), 2, fp); printf("成功读取%zu个结构体\n", read_num); // 打印读取到的数据 for (int i = 0; i < read_num; i++) { printf("\n第%d本书:\n", i+1); printf(" 原版书名:%s\n", read_books[i].title); printf(" 中文译名:%s\n", read_books[i].newtitle); printf(" 作者:%s\n", read_books[i].author); } fclose(fp); return 0; }
方法2:写完直接关文件,再重新打开读
如果你觉得fseek麻烦,也可以写完数据后直接关闭文件,再以读模式重新打开,这时候文件指针会自动回到开头:
// 写完数据后先关闭文件 fclose(fp); // 重新以只读二进制模式打开 fp = fopen("novels.dat", "rb"); if (!fp) { perror("重新打开文件失败"); return 1; } // 接下来就可以正常fread了
额外提醒几个坑
- 打开文件一定要用二进制模式(
wb+、rb),别用文本模式(w+、r),不然文本模式会自动转换换行符,把结构体的二进制数据搞乱,读出来肯定不对。 - 一定要检查
fwrite()和fread()的返回值,看看实际写入/读取了多少个元素,万一写入失败也能及时发现问题。 - 要是你的结构体里有指针成员(比如
char *title),那直接用fwrite就不行了,因为指针存的是内存地址,写入文件后再读出来地址已经失效了,但你的结构体里都是字符数组,完全没问题。
内容的提问来源于stack exchange,提问作者Dylan N.
相关产品推荐
相关产品推荐

