C++逐字节读取文件:为何代码块1返回正确字节数60008,代码块2返回错误字节数54060?
为什么两种C++逐字节读取文件的代码结果不同?
这问题很典型,核心在于你用了两种完全不同的输入方式,它们的行为差异直接导致了读取结果的不同:
代码块1为什么正确?
代码块1里的std::istreambuf_iterator<char>是直接和流的底层缓冲区打交道的,它会原封不动地读取每一个字节——不管这个字节是空白字符、空字节还是其他任何值,没有任何跳过或格式化操作。加上你已经指定了std::ios::binary模式,流不会对换行符做任何转换,所以能准确读取文件的全部字节数,结果自然是对的。
代码块2为什么会少读字节?
问题出在>>这个格式化输入运算符上,哪怕你开了二进制模式,它的行为也没你想的那么“二进制”:
- 跳过空白字符:默认情况下,
>>会根据当前locale的规则,跳过所有被std::isspace()判定为空白的字符,包括空格、换行符、制表符,甚至是ASCII值为0的空字节。如果你的二进制文件里包含大量这类字节,它们都会被直接跳过,不会被加入到bytes向量中,这就是读取总数变少的主要原因。 - 循环条件的小坑:
while (labelsFile)的写法会导致最后一次无效读取被加入向量。当流到达EOF时,labelsFile >> byte会失败,但此时循环仍然会执行bytes.push_back(byte),这时候byte的值是未定义的——不过这个问题只会多算一个字节,不是你当前结果差异的主要原因。
如何修正代码块2?
如果你想用循环逐字节读取,应该用std::ifstream::get()方法,它会读取每一个字节(包括空白和空字节),不会跳过任何内容,同时把读取操作放在循环条件里,能正确处理EOF:
std::string test_labels = "train-labels.idx1-ubyte"; std::ifstream labelsFile(test_labels, std::ios::binary); std::vector<char> bytes; char byte; // 用get()读取,读取成功才进入循环 while (labelsFile.get(byte)) { bytes.push_back(byte); } std::cout << "\nNumber of bytes read " << bytes.size() << std::endl;
内容的提问来源于stack exchange,提问作者sandy
相关产品推荐
相关产品推荐

