为什么failot当eof阅读?有出路吗? [英] Why is failbit when eof on read? Is there a way out?

查看:268
本文介绍了为什么failot当eof阅读?有出路吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经读过< fstream> predates < exception> 。忽略了在 fstream 上的异常不是很有用的事实,我有以下问题:

I've read that <fstream> predates <exception>. Ignoring the fact that exceptions on fstream aren't very informative, I have the following question:

使用 exceptions()方法对文件流启用异常。

It's possible to enable exceptions on file streams using the exceptions() method.

ifstream stream;
stream.exceptions(ifstream::failbit | ifstream::badbit);
stream.open(filename.c_str(), ios::binary);

任何尝试打开不存在的文件,没有正确权限的文件或任何其他I / O问题会导致异常。这是非常好的使用自信的编程风格。该文件应该在那里,并且可读。如果条件不满足,我们会得到一个异常。如果我不确定该文件是否可以安全地打开,我可以使用其他函数来测试它。

Any attempt to open a nonexistent file, a file without the correct permissions, or any other I/O problem will results in exception. This is very good using an assertive programming style. The file was supposed to be there and be readable. If the conditions aren't met, we get an exception. If I wasn't sure whether the file could safely be opened, I could use other functions to test for it.

但现在假设我尝试读入缓冲区,像这样:

But now suppose I try to read into a buffer, like this:

char buffer[10];
stream.read(buffer, sizeof(buffer)); 

如果流在填充缓冲区之前检测到文件结束,流决定设置 failbit ,如果启用了异常,则会触发异常。为什么?这是什么意思?我可以验证,只是测试 eof()后读:

If the stream detects the end-of-file before filling the buffer, the stream decides to set the failbit, and an exception is fired if they were enabled. Why? What's the point of this? I could have verified that just testing eof() after the read:

char buffer[10];
stream.read(buffer, sizeof(buffer));
if (stream.eof()) // or stream.gcount() != sizeof(buffer)
    // handle eof myself

此设计选项阻止我对流使用标准异常,并强制我对权限或I / O错误创建自己的异常处理。还是我错过了什么?有什么办法吗?例如,我可以轻松地测试是否可以在流之前读取 sizeof(buffer)字节?

This design choice prevents me from using standard exceptions on streams and forces me to create my own exception handling on permissions or I/O errors. Or am I missing something? Is there any way out? For example, can I easily test if I can read sizeof(buffer) bytes on the stream before doing so?

推荐答案

改进@没有答案,它遵循一个方法 readeof() ,但不在EOF上设置failbit。此外,实际读取失败已经过测试,如通过硬盘移除USB记忆棒或网络共享访问中的链接中断的中断传输。它已经在Windows 7上与VS2010和VS2013和在linux与gcc 4.8.1测试。在linux上只尝试了USB记忆棒删除。

Improving @absence's answer, it follows a method readeof() that does the same of read() but doesn't set failbit on EOF. Also real read failures have been tested, like an interrupted transfer by hard removal of a USB stick or link drop in a network share access. It has been tested on Windows 7 with VS2010 and VS2013 and on linux with gcc 4.8.1. On linux only USB stick removal has been tried.

#include <iostream>
#include <fstream>

using namespace std;

streamsize readeof(ifstream &stream, char* buffer, streamsize count)
{
    // This consistently fails on gcc (linux) 4.8.1 with failbit set on read
    // failure. This apparently never fails on VS2010 and VS2013 (Windows 7)
    streamsize reads = stream.rdbuf()->sgetn(buffer, count);

    // This rarely sets failbit on VS2010 and VS2013 (Windows 7) on read
    // failure of the previous sgetn()
    stream.rdstate();

    // On gcc (linux) 4.8.1 and VS2010/VS2013 (Windows 7) this consistently
    // sets eofbit when stream is EOF for the conseguences  of sgetn(). It
    // should also throw if exceptions are set, or return on the contrary,
    // and previous rdstate() restored a failbit on Windows. On Windows most
    // of the times it sets eofbit even on real read failure
    stream.peek();

    return reads;
}

#define BIGGER_BUFFER_SIZE 200000000

int main(int argc, char* argv[])
{
    ifstream stream;
    stream.exceptions(ifstream::badbit | ifstream::failbit);
    stream.open("<big file on usb stick>", ios::binary);

    char *buffer = new char[BIGGER_BUFFER_SIZE];

    streamsize reads = readeof(stream, buffer, BIGGER_BUFFER_SIZE);

    if (stream.eof())
        cout << "eof" << endl << flush;

    delete buffer;

    return 0;
}

底线:在linux上行为更加一致和有意义。如果在读取失败的情况下启用异常,它会抛出 sgetn()。相反,Windows会将读取失败视为大多数时候的EOF。

Bottom line: on linux the behavior is more consistent and meaningful. With exceptions enabled on real read failures it will throw on sgetn(). On the contrary Windows will treat read failures as EOF most of the times.

这篇关于为什么failot当eof阅读?有出路吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆