【问题标题】:eof bit : before or after a read failure?eof 位:在读取失败之前还是之后?
【发布时间】:2012-09-30 20:30:25
【问题描述】:

我目前正在为一些 IO 操作编写一个类。一些函数返回 IO 操作是否成功。如果我正在读取一个文件,不知是否应该返回std::ifstream::good()!std::ifstream::fail()来表示IO操作是否成功。

区别来自eof 位,我不确定我是否正确理解它。

假设我有一个包含 4 个字节(1 个整数)的二进制文件。

假设我读取了这个整数。

我的问题是:eof 标志会在此操作之后还是在下一个 IO 操作之后设置(这将失败)?

如果在这个操作之后直接设置,如果我的读取函数返回std::ifstream::good(),那么结果将是false(但是整数被正确读取了)。

你能解释我什么时候设置了 eof 位,我应该在函数结束时返回什么?

【问题讨论】:

  • 与其实现您自己的istream 类对象,不如考虑从std::streambuf 派生并通过其rdbuf() 函数将其包装在实际的istream 中。你只需要实现streambuf的几个功能,就可以免费获得istream的所有花里胡哨。 (不确定这对您的情况是否有帮助!)

标签: c++ io stream ifstream eof


【解决方案1】:

EOF 标志被设置您尝试读取流的末尾。

您的函数应该返回对原始流的引用,并且应该在循环或条件中使用它,如下所示:

std::istream & process(std::istream & is)
{
    int n;
    if (is >> n) { std::cout << "Read one int: " << n << "\n"; }
    return is;
}

int main()
{
    std::ifstread infile("data.bin");

    while (process(infile)) { }
}

【讨论】:

    【解决方案2】:

    当读取操作尝试读取超出流的末尾时,会设置流的“eof”位。读取超出流末尾的读取操作可能成功,也可能不成功。这与是否设置了“eof”位无关。

    因此,您应该始终检查读取操作本身的结果,而不是在读取后检查流标志的状态。

    所有四种组合的示例:

    #include <iostream>
    #include <istream>
    
    int main()
    {
            int n;
            if (std::cin >> n)
                    std::cout << "read an int with value = " << n << '\n';
            else
                    std::cout << "read of int failed\n";
    
            std::cout << "cin.eof() = " << std::cin.eof() << '\n';
            return 0;
    }
    

    设置 eof 位的成功读取:

    $ printf 1 | ./a.out
    read an int with value = 1
    cin.eof() = 1
    

    未设置 eof 位的成功读取:

    $ echo 1 | ./a.out
    read an int with value = 1
    cin.eof() = 0
    

    未设置 eof 位的不成功读取:

    $ printf abc | ./a.out
    read of int failed
    cin.eof() = 0
    

    设置 eof 位的读取失败:

    $ echo | ./a.out
    read of int failed
    cin.eof() = 1
    

    【讨论】:

    • 我不明白为什么第一个示例设置了 eof 位而不是第二个。你能解释一下为什么吗?
    • @Vincent:在第一个示例中,流仅包含字符 1。为了测试正在读取的整数是否为110123456789,必须尝试读取(或窥视)另一个字符,但由于没有更多字符,这将设置 eof 位。在第二个示例中,1 后跟一个换行符。读取1 后的读取尝试读取非数字(换行符),因此读取的数字在1 处完成。由于未读取流的末尾,因此未设置 eof 位。
    • 哦,好的,非常感谢!但是当我处理二进制文件时,我不需要检查下一个字符。
    • @Vincent:二进制文件可能意味着任何格式的文件。只有你知道什么是成功的阅读。如果您需要读取四个字节(字符)以进行有效读取,那么您需要(至少)测试(例如)一个四字节 read(char*, std::streamsize) 或等效调用是否成功。同样,测试读取的结果,而不是流上的标志。 (此外,您可能正在做一些乐观的阅读,例如尝试读取 16 个字节,如果调用仅读取 8 个字节,即使 eof 位已设置,您可能仍然有四分之二的成功读取。)
    【解决方案3】:

    eof 标志设置为“在下一次 IO 操作(将失败)之后”。您应该在读取操作后返回std::ifstream::good(),以告知是否设置了任何错误标志。

    【讨论】:

      猜你喜欢
      • 2018-04-28
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      相关资源
      最近更新 更多