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

为何调用fread()读取后文件流指针位置出现异常变动?

二进制文件读取后文件指针位置异常的问题

我尝试用fread()从文件读取二进制数据,但读取后文件流的当前位置会因文件不同而变化。我运行了以下测试代码:

#include <stdio.h>

int main(int argc, char** argv) {
    FILE* in = fopen(argv[1], "r");
    char buff[10];
    fseek(in, 0, SEEK_SET);
    fread(buff, sizeof(char), 10, in);
    printf("Final position: %d\n", (int)ftell(in));
    return 0;
}

控制台输出(运行环境:Windows,编译器为MinGW的g++.exe):

$ ./p.exe test_data/test_elf
Final position: 692
$ ./p.exe test_data/test.cc
Final position: 11
$ ./p.exe example.txt 
Final position: 9

我预期最终位置应该是10,因为从位置0开始读取了10字节,但实际结果不符,请问哪里出错了?


更新:文件内容的十六进制dump

example.txt:

$ hexdump example.txt 
0000000 3231 3433 3635 3837 3039 6261 6463 6665
0000010 6867 6a69 6c6b 6f6e 7170 7372 7574 7776
0000020 7978 207a 2320 2524 265e 282a e229 9684
0000030 253b 3f3a 282a 7b29 5b7d 0a5d
000003c

test_data/test.cc:

$ hexdump test_data/test.cc
0000000 0a0d 7361 286d 6e22 706f 2922 0d3b 610a
0000010 6d73 2228 756c 2069 3278 202c 7830 3031
0000020 2230 3b29 2020 2020 2020 2020 2020 2020
0000030 2020 2f2f 5320 2050 6573 2074 6f74 3120
... (more)

test_data/test_elf:

$ hexdump test_data/test_elf
0000000 457f 464c 0101 0001 0000 0000 0000 0000
0000010 0002 00f3 0001 0000 0074 0001 0034 0000
0000020 0334 0000 0000 0000 0034 0020 0002 0028
0000030 0008 0007 0001 0000 0000 0000 0000 0001
... (more)

问题原因

你用"r"模式打开文件,这是文本模式,在Windows系统下会触发两个关键行为,导致文件指针位置不符合预期:

  1. 换行符转换:Windows文本模式会自动将文件中的\r\n(十六进制0D 0A)转换为单个\n字符。比如test.cc开头的0D 0A会被当成一个逻辑字符,当你读取10个逻辑字符时,实际跳过了11个物理字节,因此ftell返回11。
  2. EOF字符截断:DOS/Windows文本模式下,字节0x1A会被视为文件结束标记。test_elf作为二进制文件,在偏移692的位置恰好有这个字节,导致fread提前终止,指针停在692。
  3. 对于example.txt,文本模式下的隐性字符处理导致读取计数与物理字节偏移出现偏差,最终指针停在9。

解决方法

将文件打开模式改为二进制模式"rb",这样系统不会做任何字符转换,也不会把0x1A当成文件结束标记,fread读取的字节数和文件指针移动的位置完全对应。

修改后的代码:

#include <stdio.h>

int main(int argc, char** argv) {
    FILE* in = fopen(argv[1], "rb"); // 改为二进制模式
    char buff[10];
    fseek(in, 0, SEEK_SET);
    fread(buff, sizeof(char), 10, in);
    printf("Final position: %d\n", (int)ftell(in));
    return 0;
}

修改后运行,无论读取哪种文件,ftell都会返回预期的10。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 17:25:53