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

C语言中fread无法读取二进制文件内Node对象的问题排查

Why fread Returns 0 When Reading Node Structs

Let’s break down the most common reasons for this issue and how to fix them:

1. Incorrect File Opening Mode (Critical for Windows)

If your showMapTerrain function opens the file in text mode ("r" instead of "rb"), Windows will modify binary data during reading (e.g., converting \n to \r\n). This shifts the file pointer out of alignment with the Node data written by addToFile (which presumably uses "wb" for binary write), causing fread to hit an unexpected EOF and return 0.

Fix: Always open binary files in binary mode for both reading and writing:

// In showMapTerrain
FILE *fp = fopen("map_data.bin", "rb");
// In addToFile
FILE *fp = fopen("map_data.bin", "wb");

2. Struct Padding Mismatch Between Write and Read

Your Node struct contains mixed data types (floats, int, pointer), which compilers often pad with extra bytes to align members to memory word boundaries. If addToFile and showMapTerrain are compiled with different padding settings (e.g., one uses -fpack-struct and the other doesn’t), the total size of Node will differ. This misalignment means the data written to the file doesn’t match the size you’re trying to read, leading to eventual EOF.

Fixes:

  • Use consistent compiler settings: Ensure both functions are compiled with the same struct packing options.
  • Explicitly disable padding: Use compiler directives to force the struct to be packed without padding (note: this may affect performance):
    #pragma pack(push, 1) // Disable padding
    struct Node {
        float height;
        int terrainType;
        float visitsCount;
        struct Node *next;
    } Node;
    #pragma pack(pop) // Restore default padding
    
  • Read/write only relevant fields: Since the next pointer is a memory address (useless when read back), avoid padding issues by writing/reading only meaningful fields instead of the entire struct:
    // Writing a Node (in addToFile)
    fwrite(&node->height, sizeof(float), 1, fp);
    fwrite(&node->terrainType, sizeof(int), 1, fp);
    fwrite(&node->visitsCount, sizeof(float), 1, fp);
    
    // Reading a Node (in showMapTerrain)
    Node temp;
    if (fread(&temp.height, sizeof(float), 1, fp) != 1) break;
    if (fread(&temp.terrainType, sizeof(int), 1, fp) != 1) break;
    if (fread(&temp.visitsCount, sizeof(float), 1, fp) != 1) break;
    // Ignore the next pointer since we don't need it (or allocate a new list if needed)
    

3. Writing the Useless next Pointer

The next member of your Node struct is a memory address from the writing process. Writing this to the file is unnecessary and can introduce padding-related issues. Even if you read it back, the pointer value will be invalid in the reading process.

Fix: Modify addToFile to exclude the next pointer when writing. Use the field-by-field write method shown above to avoid padding problems and reduce file size.

4. Missing Error Checking

Always verify the return values of fopen, fread, and fwrite to catch unexpected issues early:

FILE *fp = fopen("map_data.bin", "rb");
if (!fp) {
    perror("Failed to open file");
    return 1;
}

// After reading floats:
if (fread(&float1, sizeof(float), 1, fp) != 1) {
    perror("Failed to read first float");
    fclose(fp);
    return 1;
}

内容的提问来源于stack exchange,提问作者Platon Makovsky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:19:19