fwrite写入stdout出现额外0x0D字节插入的技术问题咨询
fwrite到stdout时出现额外0x0D字节的原因及解决方法
你遇到的这个问题其实是Windows系统下C标准库流模式的典型“坑”——标准输出流stdout默认处于文本模式,而不是二进制模式,这导致换行符被自动转换,最终在重定向生成的文件中多出了0x0D字节。
问题原因分析
- Windows系统中,C标准库的文件流分为文本模式和二进制模式:
- 文本模式下,写入
\n(0x0A)时,系统会自动将其转换为Windows换行格式\r\n(0x0D 0x0A);读取时则反向转换。 - 二进制模式下,数据会原封不动地读写,不会做任何字符转换。
- 文本模式下,写入
- 你写入
file.txt时使用了fopen("file.txt", "wb")的wb标志(二进制写入),所以数据完全和原文件一致;但stdout默认是文本模式,即使你用fwrite写入二进制数据,只要流是文本模式,Windows就会自动处理换行符。 - 当你用
program.exe > stdout.txt重定向输出时,stdout的文本模式依然生效,所以输出到文件的过程中,每个0x0A前都被插入了0x0D,最终出现3个额外字节。
验证你的测试结果
你提到把代码第16行true改为false后,程序输出三个偏移位置:
6ec : d, a c68 : d, a ecc : d, a
这正好对应原文件original.txt中三个0x0A的位置——stdout.txt里这些位置的字节变成了0x0D,而原数据是0x0A,完全符合文本模式下的换行符转换规则。
解决方法:将stdout设置为二进制模式
要让stdout以二进制模式输出,需要在写入数据前修改流的模式。在Windows下可以使用_setmode函数(需要包含对应头文件),同时为了跨平台兼容,我们可以加上条件编译:
修改你的代码,在fwrite(&read_data[0], 1, 0x1000, stdout);之前添加以下代码:
#ifdef _WIN32 #include <io.h> #include <fcntl.h> // 将stdout设置为二进制模式 _setmode(_fileno(stdout), _O_BINARY); #endif
修改后,再执行program.exe > stdout.txt,生成的stdout.txt就会和file.txt、原文件完全一致,不会再有额外的0x0D字节。
补充说明
- Linux/macOS等类Unix系统没有文本模式和二进制模式的区别,所有流默认都是二进制模式,所以在这些系统上不会出现这个问题。
- 如果你需要保证跨平台的二进制输出一致性,添加上述条件编译代码是最佳实践。
内容的提问来源于stack exchange,提问作者Federal_Reserve
相关产品推荐
相关产品推荐

