istream::read 和 istream::operator 之间的区别>>

Difference between istream::read and istream::operator>>

本文关键字:istream gt 区别 之间 read operator      更新时间:2023-10-16

这里有两个代码片段,我最初认为它们应该是等效的:

{
    std::ifstream stream("test.bin", std::ios_base::in | std::ios_base::binary);
    unsigned char count = 128;
    unsigned char read = 0;
    unsigned char scanline[128];
    long long start = stream.tellg();
    while (count--) {
        stream >> scanline[read++]; // <---- This is the only line which differs
    }
    long long end = stream.tellg();
    std::cout << end - start << "n";
}
{
    std::ifstream stream("test.bin", std::ios_base::in | std::ios_base::binary);
    unsigned char count = 128;
    unsigned char read = 0;
    unsigned char scanline[128];
    long long start = stream.tellg();
    while (count--) {
        stream.read((char*)&scanline[read++], 1); // <---- This is the only line which differs
    }
    long long end = stream.tellg();
    std::cout << end - start << "n";
}

我的问题是第一个版本输出 153(可能取决于输入数据),第二个版本输出 128(这是我预期的)。这一定与第一个版本中的数据提取方式有关,但我不明白为什么它不起作用。它不应该只是调用:

istream& operator>> (istream& is, unsigned char& ch);

并且每次移动文件一个字节?

如果您阅读operator>>的描述(例如这里),那么您会看到它在阅读之前跳过空格,直到再次遇到空格。空格不仅是空格(0x20),还包括制表符(0x09)和换行符(0x0a)。

因此,如果您的二进制数据包含被视为文本文件的空格的字节,那么operator>>将读取但不存储它们,这将扭曲 tellg 报告的数字。

二进制中打开流时使用该operator>>不是一个好主意。
我假设在您的情况下,您的流中有某种空格字符(例如0x20)。
您可以使用 skipws 修饰符来读取这些内容。