当参数是目录时,ifstream open() 不会设置错误位

Ifstream open() doesn't set error bits when argument is a directory

本文关键字:设置 错误 open ifstream 参数      更新时间:2023-10-16

在C++程序中,使用std::ifstream,我正在尝试打开用户指定的文件 - 到目前为止一切顺利。但是,我不小心输入了一个实际上是目录的文件名,我很惊讶地看到尝试打开((该目录没有产生任何错误。

下面是一个最小示例:

std::ifstream f;
f.open("..");
if(!f.is_open() || !f.good() || f.bad() || f.fail()) {
    std::cout << "error bit set on open" << std::endl;
    return 1;
}

这里没有错误的迹象。如果我继续尝试 getline((,getline(( 设置一个错误位就可以了。

std::string str;
getline(f, str);
if(f.eof()) std::cout << "getline set eofbit" << std::endl;
else if(f.bad()) std::cout << "getline set badbit" << std::endl;
else if(f.fail()) std::cout << "getline set failbit" << std::endl;

这输出"getline set badbit",这是合理的。使用>> 运算符会引发下溢异常,这也是可以的。

现在,我的问题是,如何检测用户输入了目录名称而不是正确的文件名?有什么办法可以做到这一点吗?从流中获取和取消获取字节似乎很乏味且容易出错。

另外,为什么会这样?我意识到从程序的角度来看,这一切都是相同的数据,但我认为操作系统也会发送一些"嘿,这是一个目录"类型的消息。

你不说你的系统是什么,所以很难说,但一般来说, filebuf::open 只会在系统级别打开时返回错误失败。 我曾经在Unix系统上工作过,你可以open()目录;我什至做过一些你可以在之后阅读它的地方打开(至少如果它是一个本地挂载的文件系统(。

至于该怎么办:我能想到的就是试着get第一个字符,然后将其放回原处。 但是,如果文件是空的,所以它也不是真正的解决方案。 在系统级别(和从 QoI 的角度来看,我希望filebuf::open这样做,如果系统确实允许打开目录(,您可以使用系统级调用( stat 在 Unix 中(来确定文件是否为目录。(当然,有一个竞争条件:在你检测到的那一刻之间这是一个普通的文件,当你打开的那一刻,另一个过程可以删除文件并创建一个目录。 它可能不是一个但是,经常发生。