2011-01-26 74 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); 
} 

如果這是你需要的模式。

沒有什麼神奇的方式來打開一個文件進行讀/寫創建它,如果它不存在但不截斷它(刪除其內容),如果它。你必須通過多個步驟來完成。