是否可以在 ios::in 和 ios::out 都不存在的文件上打开 fstream 而不会出现错误?
5 回答
不幸的是,您的问题的答案是:“不”,这在单个 C++ 语句中是不可能的。
是的,很多人会回答,你可以使用组合标志fstream::in | fstream::out | fstream::trunc
。但这个答案是胡说八道。fstream::trunc
意味着,输出文件将在打开时被截断为零大小。但是,为什么要打开一个空文件进行读写呢?除了极少数情况,您需要一个文件作为应用程序的某些数据的临时存储,您将先写入然后再读回,此标志组合没有用处。
有些人建议首先尝试打开fstream::in | fstream::out
(以及可能的其他标志,如fstream:app
或fstream::binary
根据需要),然后检查文件的错误状态:如果文件无法打开,则重新尝试打开操作,包括| fstream::trunc
. 但是,此解决方案有几个注意事项。例如,如果您的文件系统是通过 NFS 挂载的,则第一次尝试以读/写模式打开文件可能会由于临时网络问题而失败。如果第二次尝试(包括fstream::trunc
旗帜的那次)成功,那么您收集的数据就会丢失。
安全的解决方案是首先打开文件仅用于附加(如果文件不存在,它将创建文件,但不会截断它),然后立即关闭它并以读写模式再次打开它。这可以通过以下代码来实现: 注意,ofstream
首先构造 an,然后立即丢弃。
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ostream::app);
std::fstream file(filename);
或者,如果您需要更多标志,例如binary
,请使用:
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ofstream::app | std::fstream::binary);
std::fstream file(filename, std::fstream::in | std::fstream::out | std::fstream::binary);
我希望,在 C++25(或下一个标准)中std::fstream::create
,如果请求读写模式,他们最终会添加一个标志来创建不存在的输出文件。
#include <fstream>
ofstream out("test", ios::out);
if(!out)
{
cout << "Error opening file.\n";
return 1;
}
ifstream in("test", ios::in);
if(!in)
{
cout << "Error opening file.\n";
return 1;
}
如果发生错误,则会显示消息并返回一 (1)。然而,编译和执行是可能的ofstream out("test", ios::out);
,ifstream in("test", ios::in);
没有任何错误。无论哪种方式,都会创建文件测试。
#include <iostream>
#include <fstream>
using namespace std;
int main () {
fstream f("test.txt", fstream::in | fstream::out);
cout << f.fail() << endl;
f << "hello" << endl;
f.close();
return 0;
}
1
如果不退出,此代码将打印并且不会创建“test.txt”文件。因此,不可能在不存在错误的情况下打开和 fstream 处理不存在的文件。
std::fstream f("test.txt", std::ios_base::out);
f.close(); //file now exists always
f.open("test.txt", fstream::in | std::ios_base::out);
//f is open for read and write without error
我还没有检查以保证它会毫无错误地打开,但我很有信心它应该这样做。