文件足够大时std::fread应成功?VS2015读取异常咨询
问题分析与解决方案
这不是Visual Studio 2015的Bug,而是误用文件打开模式导致的预期外行为,下面详细拆解原因和修复方法:
核心问题:文本模式与二进制模式的差异
你用L"r"(文本模式)打开了一个二进制格式的.data文件,而Windows平台的C标准库对文本模式有特殊处理逻辑:
- 文本模式下,库会自动转换换行符(将
\r\n转为\n) - 更关键的是,当读取到字节
0x1A(DOS/Windows传统EOF标记,对应键盘Ctrl+Z)时,会被判定为文件结束,此时fread会停止读取,返回已读取的字节数,且errno保持为0——因为库认为这是正常的文本文件结束场景。
你的80MB文件恰好在第3473字节位置出现了0x1A字符,才会出现请求读取16384字节却仅返回3473字节的情况。
修复方法:使用二进制模式打开文件
处理二进制数据时,必须用二进制模式打开,只需将打开模式改为L"rb":
#include <cstdio> #include <vector> int main() { std::FILE* file; errno_t error = _wfopen_s(&file, L"/User/account/Desktop/file.data", L"rb"); // 务必检查文件是否成功打开 if (error != 0) { // 处理打开失败逻辑,比如打印错误信息 return 1; } const std::size_t n = 16384; std::vector<unsigned char> v(n); const std::size_t nb_bytes_read = std::fread(v.data(), sizeof(unsigned char), n, file); // 现在只要文件剩余字节足够,就能读取到预期的16384字节 std::fclose(file); // 别忘了关闭文件资源 return 0; }
补充说明
- Unix/Linux平台上文本模式和二进制模式无差异,但为了跨平台兼容性,处理二进制文件时始终使用
"rb"/"wb"等二进制模式是最佳实践。 - C标准明确允许文本模式对输入输出进行特定转换(包括识别特殊EOF标记),所以这种行为是符合标准的,并非编译器或库的Bug。
内容的提问来源于stack exchange,提问作者InsideLoop
相关产品推荐
相关产品推荐

