Fstream无法创建新文件

时间:2011-01-26 15:53:26

标签: c++ file file-io

我正在使用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::openmodestd::ios::in | std::ios::out。当我只标记std::ios::out时,我可以很好地创建文件,但我希望将流保持在读/写状态。

我该如何做到这一点?

6 个答案:

答案 0 :(得分: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);
}

因此代码测试现有文件,如果没有,则创建它。

答案 1 :(得分:3)

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

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

代替(但要确保它不存在或者它将被截断为零字节)。

答案 2 :(得分:3)

您必须使用

的明确fstream::open参数调用openmode
ios_base::in | ios_base::out | ios_base::trunc

否则open会因ENOENT而失败。

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

(冒着被嘲笑的风险:你可以切换到stdio并使用文件模式a+,它从头开始读取并在末尾追加。)

答案 3 :(得分:3)

  

我该如何做到这一点?

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

这不是更简单吗?

答案 4 :(得分:2)

这就是图书馆工作的方式:std::ios::in | std::ios::out以相当于stdio的{​​{1}}打开它,也就是说它只会打开现有文件。我不相信有一种模式会做你想要的,你将需要我们一个特定于操作系统的调用或检查文件是否存在(再次,使用特定于操作系统的调用)并以一种模式打开它或另一个取决于它是否已经存在。

编辑:我认为如果文件已经存在,您不希望文件被截断。正如其他人所说,如果你很乐意截断任何现有文件,那么"r+"是一个选项。

答案 5 :(得分: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);
}

如果这是您需要的模式。

没有神奇的方法可以打开文件进行读/写创建,如果它不存在但不截断它(删除它的内容),如果有的话。你必须分多步完成。

相关问题