繁体   English   中英

Fstream无法创建新文件

[英]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::openmodestd::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::inr+ 我上面列出的那个相当于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM