[英]Fstream fails to create new file
我正在使用FileManager进行项目,这样我的阅读和写作就不那么麻烦了。 或者,如果我没有花费所有这些时间调试它。 所以,这种舒适的课程实际上给我带来了压力和时间。 真棒。
问题似乎是fstream
。 在继续之前,这是我的FileManager类的结构。
class FileManager : Utility::Uncopyable
{
public:
FileManager();
void open(std::string const& filename);
void close();
void read(std::string& buffer);
void write(std::string const& data);
private:
std::fstream stream_;
};
很简单。 缓冲区在读取功能期间加载数据,数据参数是要写入文件的内容。 在阅读和写作之前,你必须打开文件,否则就有可能在你脸上出现一个很大的例外。 有点像我现在得到的那个。
场景:简单命令行注册用户,然后将数据写入文件。 我要一个名字和密码。 该名称将被复制并附加.txt(文件名)。 所以它看起来像这样:
void SessionManager::writeToFile(std::string const& name,
std::string const& password)
{
std::string filename = name + ".txt";
std::string data;
data += name +", " +password;
try
{
fileManager_->open(filename);
fileManager_->write(data);
fileManager_->close();
}
catch(FileException& exception)
{
/* Clean it up. */
std::cerr << exception.what() << "\n";
throw;
}
}
问题:打开失败。 永远不会创建该文件,并且在写入期间,由于没有打开文件,我会收到异常。
FileManager :: open()函数:
void FileManager::open(std::string const& filename)
{
if(stream_.is_open())
stream_.close();
stream_.open(filename.c_str());
}
和写
void FileManager::write(std::string const& data)
{
if(stream_.is_open())
stream_ << data;
else
throw FileException("Error. No file opened.\n");
}
但是,如果我事先创建文件,那么打开文件没有麻烦。 然而,当我检查时,默认的std::ios::openmode
是std::ios::in | std::ios::out
std::ios::in | std::ios::out
。 当我只标记std::ios::out
,我可以创建文件,但我希望将流保持在读/写状态。
我怎么能做到这一点?
最佳方法:
void FileManager::open(std::string const& filename)
{
using std::ios_base;
if( stream_.is_open() )
stream_.close();
stream_.open( filename.c_str() ); // ...try existing file
if( !stream_.is_open() ) // ...else, create new file...
stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc);
}
因此代码测试现有文件,如果没有,则创建它。
您不能std::ios::in
不存在的文件上使用std::ios::in
。 采用
std::ios::in | std::ios::out | std::ios::trunc
相反(但要确保它不存在或者它将被截断为零字节)。
你必须使用显式的openmode
参数调用fstream::open
ios_base::in | ios_base::out | ios_base::trunc
否则,由于ENOENT
open
将失败。
C ++标准草案的表95列出了可能的文件打开模式及其在stdio
的等价物。 默认ios_base::out | ios_base::in
ios_base::out | ios_base::in
是r+
。 我上面列出的那个相当于w+
。 ios_base::out | ios_base::app
ios_base::out | ios_base::app
相当于a
。 涉及ios_base::app
所有其他组合均无效。
(冒着被嘲笑的风险:你可以切换到stdio
并使用文件模式a+
,它从开头读取并在最后附加。)
我怎么能做到这一点?
std::ofstream file("file.txt");
file << data;
这不是更简单吗?
这就是库的工作方式: std::ios::in | std::ios::out
std::ios::in | std::ios::out
在相当于stdio
的"r+"
打开它,即它只会打开一个现有文件。 我不相信有一种模式会做你想要的,你将需要我们一个特定于操作系统的调用或检查文件是否存在(再次,使用特定于操作系统的调用)并以一种模式打开它或另一个取决于它是否已经存在。
编辑 :我认为如果文件已经存在,您不希望文件被截断。 正如其他人所说,如果你很乐意截断任何现有文件,那么in | out | trunc
in | out | trunc
in | out | trunc
是一个选项。
只需让你的功能打开
void FileManager::open(std::string const& filename)
{
using std::ios_base;
if(stream_.is_open())
stream_.close();
stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc);
}
如果那是你需要的模式。
没有神奇的方法可以打开文件进行读/写创建,如果它不存在但不截断它(删除它的内容),如果它存在的话。 你必须分多步完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.