You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二进制文件(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(&currentAge, 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:47:50