【问题标题】:What Is Throwing The Exception In This File Stream?什么是在此文件流中引发异常?
【发布时间】:2014-08-16 13:59:55
【问题描述】:

我不明白是什么在我的输入文件流中引发了异常。我以前做过几乎完全一样的事情,没有任何问题。

std::string accnts_input_file = "absolute_path/account_storage.txt";
std::string strLine;
std::ifstream istream;
istream.exceptions( std::ifstream::failbit | std::ifstream::badbit );

try
{
    istream.open( accnts_input_file.c_str() );

    while( std::getline( istream, strLine ) )
    {
        std::cout << strLine << '\n';
    }

    istream.close();
}
catch( std::ifstream::failure &e )
{
    std::cerr << "Error opening/reading/closing file" << '\n'
              << e.what()
              << std::endl;
}

我只让它打印它现在读取的行来尝试跟踪错误。它逐行读取文件并打印它们,然后抛出异常。异常说 basic_ios::clear,我不明白。我认为抛出异常的是 ifstream::failbit ,因为当我只设置 ifstream::badbit 时它不会抛出异常,但我不知道为什么。我也尝试过“while(!istream.oef())”和大多数其他方法,而不是“while(std::getline(istream, strLine))”,但我一直收到同样的错误。

我确定这可能是我明显遗漏的东西,但我们将不胜感激。谢谢

【问题讨论】:

  • 到达 EOF 时对 std::getline( istream, strLine ) 的最后一次调用可能会设置 istream 的故障位。
  • 为什么不尝试从异常中打印更多信息?例如,使用what 成员函数。
  • 您可以尝试在您的catch 中打印e.what()
  • @πάντα ῥεῖ - 如果达到 eof,它不会抛出 eofbit 吗?
  • 当我将 e.what() 放入 catch 语句时,它给了我 basic_ios::clear。我不明白,我想清楚刚刚清除了你的标志

标签: c++ ifstream


【解决方案1】:

来自this std::getline reference

...
a) 输入的文件结束条件,在这种情况下,getline 设置eofbit
...
3) 如果由于某种原因没有提取字符(甚至没有被丢弃的分隔符),getline 设置failbit 并返回。

这意味着在文件结束条件下,该函数设置 both eofbitfailbit。当您在设置failbit 时要求获取异常时,库会引发异常。

【讨论】:

  • 这样做的更好方法是什么?
  • 对我来说似乎是一个错误,或者至少 getline() 的设计不好
  • @Slava 我认为标准库行为的设计通常可以被认为是经过深思熟虑的,并且可能打算涵盖更多用例,正如您从直接的具体点看到的那样。恕我直言(必须从文档中检查)故障位,仅表示对 std::istream 的最后一次提取操作失败,因此 getline()(或任何其他提取操作)的设计为 EOF 情况设置它是绝对好的。
【解决方案2】:

当您尝试从流中读取但没有任何内容可读取时,读取操作将失败(= 在 getline 的第二个参数表示的变量中未插入任何字符)故障位已设置,在您的情况下为异常被抛出。

使用while(!ifstream.eof()) 仅在您的文件没有以换行符结尾时才有帮助。仅当到达流的末尾时才设置 eofbit,即读出流的每个内容。但是如果文件以换行符结尾,则读取操作将失败,而之前没有设置 eofbit。

【讨论】:

  • 我该如何解决这个问题?这样做的更好方法是什么?
  • 捕获异常后可以检查是否设置了eofbit。如果你知道一切都很好并且你不必退出你的程序(或者在 I/O 失败的情况下你想做的任何事情)。
  • @anacy 看起来您需要手动检查是否设置了没有 eofbit 的故障位并将其视为错误条件
  • @Slava - 做这样的事情会有什么好的设计?
  • @anacy 可能会编写您自己的 getline,它将拦截 std::ifstream::failure 并仅在未设置 eofbit 时重新抛出它。
【解决方案3】:

可能的解决方案之一:

bool mygetline( std::istream &in, std::string &s )
{
    try {
        return std::getline( in, s );
    }
    catch( std::ifstream::failure & )
    {
         if( !in.eof() ) throw;
         return false;
    }
}

std::string accnts_input_file = "absolute_path/account_storage.txt";
std::string strLine;
std::ifstream istream;
istream.exceptions( std::ifstream::failbit | std::ifstream::badbit );

try
{
    istream.open( accnts_input_file.c_str() );

    while( mygetline( istream, strLine ) )
    {
        std::cout << strLine << '\n';
    }

    istream.close();
}
catch( std::ifstream::failure &e )
{
    std::cerr << "Error opening/reading/closing file" << '\n'
              << e.what()
              << std::endl;
}

【讨论】:

    猜你喜欢
    • 2015-12-06
    • 1970-01-01
    • 2017-05-22
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 2012-10-13
    相关资源
    最近更新 更多