2011-01-26 79 views
6

我正在为项目使用FileManager,因此阅读和写作对我来说不是一件麻烦事。或者,如果我没有花这么多时间调试它。所以,这种舒适等级实际上给我带来了压力和时间。真棒。Fstream无法创建新文件

问题似乎是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; 
    } 
} 

问题:打开失败。该文件从不创建,并且在写入期间,我得到一个没有打开文件的例外。

文件管理:: 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::openmodestd::ios::in | std::ios::out。当我只标记std::ios::out时,我可以创建该文件,但我希望保持流处于读/写状态。

我该如何做到这一点?

回答

7

最佳方法:

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); 
} 

因此,对于现有的文件中的代码测试,如果没有,创建它。

2

这就是图书馆的工作方式:std::ios::in | std::ios::out打开它相当于stdio"r+",也就是说它只会打开一个现有的文件。我不相信有一种模式可以满足您的要求,您需要针对特定​​操作系统调用或检查文件是否存在(再次使用特定于操作系统的调用)并在一种模式下打开它,或者另一个取决于它是否已经存在。

编辑:我认为你不希望文件被截断,如果它已经存在。正如其他人已经指出,如果你很高兴截断任何现有的文件,然后in | out | trunc是一个选项。

3

您不能在不存在的文件上使用std::ios::in。使用

std::ios::in | std::ios::out | std::ios::trunc 

代替(但要确保它不存在,或者它会被截断至零个字节)。

3

你必须调用fstream::open

ios_base::in | ios_base::out | ios_base::trunc 

一个明确的说法openmode否则open将失败的原因ENOENT

C++标准草案的表95列出了可能的文件打开模式及其等效文件stdio。默认ios_base::out | ios_base::inr+。我上面列出的那个相当于w+ios_base::out | ios_base::app相当于a。涉及ios_base::app的所有其他组合均无效。

(在被嘲笑的风险:您可以切换到stdio和使用文件模式a+,它从一开始读取并追加在结尾)

+0

由于C++ 11,`ios_base :: app`本身是允许的,并且等同于“a”。有关更新的表,请参见C++ 11或C++ 14中的表132。 – 2016-01-29 00:19:30

3

我怎样才能做到这一点?

std::ofstream file("file.txt"); 
file << data; 

是不是很简单?

+0

“,但我想保持流处于读/写状态。” – 2011-01-26 16:20:19

1

只是让你的函数打开

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); 
} 

如果这是你需要的模式。

没有什么神奇的方式来打开一个文件进行读/写创建它,如果它不存在但不截断它(删除其内容),如果它。你必须通过多个步骤来完成。