二进制文件(int+10char格式)数据无法正确写入文本文件的问题
分析并修复你的二进制文件读写问题
我帮你拆解下代码里的核心问题,再给出可运行的修复方案:
核心问题拆解
1. 内存分配逻辑完全错误
你当前的代码每次循环都在重新分配单个int和11个char的内存,这意味着新读取的数据会直接覆盖之前的内容,根本没空间存储所有记录。而且realloc的用法完全跑偏——你需要的是随着读取记录数增加,扩容数组来保存所有数据,而不是每次都重置回单个元素的大小。
2. feof的使用时机错误
feof(f)应该在读取操作完成后判断,而不是读取前。如果提前判断,当文件指针到末尾时,你还是会执行一次fread,导致读取失败却依然处理错误的未初始化数据。
3. 字符串缺少终止符
你的二进制文件每个记录是10个char,但代码里读了11个?不对,应该读10个char后手动添加'\0'作为字符串终止符,否则用%s输出时会因为找不到终止符打印乱码。
4. 输出循环被注释
你把遍历所有记录的for循环注释掉了,所以不管读了多少条数据,最后只输出了被覆盖的最后一组错误数据。
5. 无效的内存释放
比如当Number_Filep == NULL时,你调用free(Number_Filep)——NULL指针不需要free,这属于无效操作,可能触发未知问题。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> void Task2_and_3() { // 用动态数组存储所有记录,初始为空 int *ageList = NULL; char **nameList = NULL; int recordCount = 0; FILE *binFile; // 打开二进制文件 if ((binFile = fopen("Test2.bin", "rb")) == NULL) { printf("Failed to open binary file"); exit(1); } // 循环读取记录:先执行读取,再判断是否成功 while (1) { int currentAge; char currentName[11]; // 10个数据位 + 1个终止符位 // 读取单个int和10个char size_t ageRead = fread(¤tAge, sizeof(int), 1, binFile); size_t nameRead = fread(currentName, sizeof(char), 10, binFile); // 读取失败(到达文件末尾或出错)则终止循环 if (ageRead != 1 || nameRead != 10) { break; } // 给字符串添加终止符,确保printf能正确识别 currentName[10] = '\0'; // 扩容存储数组:为新记录腾出空间 int *tempAge = realloc(ageList, sizeof(int) * (recordCount + 1)); char **tempName = realloc(nameList, sizeof(char*) * (recordCount + 1)); // 检查内存分配是否成功,失败则清理资源后退出 if (tempAge == NULL || tempName == NULL) { for (int i = 0; i < recordCount; i++) { free(nameList[i]); } free(ageList); free(nameList); fclose(binFile); printf("Memory allocation failed"); exit(3); } ageList = tempAge; nameList = tempName; // 保存当前记录:int直接赋值,字符串需要单独分配内存拷贝 ageList[recordCount] = currentAge; nameList[recordCount] = malloc(sizeof(char) * 11); if (nameList[recordCount] == NULL) { // 清理已分配资源 for (int i = 0; i < recordCount; i++) { free(nameList[i]); } free(ageList); free(nameList); fclose(binFile); printf("Memory allocation failed"); exit(3); } strcpy(nameList[recordCount], currentName); recordCount++; } fclose(binFile); // 写入文本文件 FILE *txtFile; if ((txtFile = fopen("Data.txt", "w")) == NULL) { printf("Failed to open text file"); // 先释放已分配的内存 for (int i = 0; i < recordCount; i++) { free(nameList[i]); } free(ageList); free(nameList); exit(4); } // 遍历所有记录写入文本 for (int n = 0; n < recordCount; n++) { fprintf(txtFile, "Name: %s\n", nameList[n]); fprintf(txtFile, "Age: %d\n", ageList[n]); } fclose(txtFile); // 释放所有动态分配的内存,避免泄漏 for (int i = 0; i < recordCount; i++) { free(nameList[i]); } free(ageList); free(nameList); }
关键修复说明
- 动态数组扩容:用
int*存储所有年龄,char**存储所有名字(每个名字单独分配内存),每次读取一条记录就扩容数组。 - 正确的读取判断:通过
fread的返回值判断读取是否成功,避免feof提前判断导致的多读问题。 - 字符串终止符:读取10个char后手动添加
'\0',确保字符串能被正确输出。 - 完整资源清理:任何出错场景都先释放已分配内存,避免内存泄漏。
- 恢复输出循环:遍历所有读取到的记录,逐个写入文本文件。
内容的提问来源于stack exchange,提问作者Jordan Baller
相关产品推荐
相关产品推荐

