2011-01-26 10 views
6

बनाने के लिए मैं एक परियोजना के लिए एक FileManager उपयोग कर रहा हूँ ताकि पढ़ने और लिखने मेरे लिए एक परेशानी का कम है विफल रहता है। या होगा, अगर मैंने इस बार इसे डिबगिंग नहीं किया था। तो, इस आराम वर्ग ने वास्तव में मुझे तनाव और समय का कारण बना दिया। बहुत बढ़िया।Fstream नई फ़ाइल

समस्या fstream हो रहा है। आगे बढ़ने से पहले, यहां मेरी फ़ाइल प्रबंधक श्रेणी की संरचना है।

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 :: खुला() फ़ंक्शन:

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::outstdio के "r+" के बराबर में यह खोलता है, कि यह केवल किसी मौजूदा फ़ाइल को खुलेगा। मुझे विश्वास नहीं है कि एक ऐसा तरीका है जो आप जो चाहते हैं वह कर देगा, आपको हमारे पास ओएस-विशिष्ट कॉल करना होगा या अस्तित्व के लिए फ़ाइल की जांच करनी होगी (फिर, ओएस-विशिष्ट कॉल का उपयोग करके) और इसे एक मोड में खोलें या दूसरा यह निर्भर करता है कि यह पहले से मौजूद है या नहीं।

संपादित करें: मुझे लगता है कि यदि आप पहले से मौजूद हैं तो फ़ाइल को छोटा कर दिया नहीं गया था। जैसा कि अन्य लोगों ने ध्यान दिया है, यदि आप किसी मौजूदा फ़ाइल को छोटा करने में प्रसन्न हैं तो in | out | trunc एक विकल्प है।

3

आप एक गैर-मौजूद फ़ाइल पर std::ios::in उपयोग नहीं कर सकते।

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

इसके बजाय (लेकिन सुनिश्चित करें कि यह अस्तित्व में नहीं है या इसे शून्य बाइट्स में छोटा कर दिया जाएगा) का उपयोग करें।

3

आप

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

की एक स्पष्ट openmode तर्क के साथ fstream::open कॉल करने के लिए नहीं तो openENOENT की वजह से असफल हो जायेगी है।

मसौदा सी ++ मानक सूचियों संभव फ़ाइल खुला मोड और stdio में उनके समकक्ष-सूची 95।डिफ़ॉल्ट, ios_base::out | ios_base::inr+ है। ऊपर सूचीबद्ध एक है जो w+ के बराबर है। ios_base::out | ios_base::appa के बराबर है। ios_base::app से जुड़े अन्य सभी संयोजन अमान्य हैं।

(मजाक उड़ाया जा रहा है पर का खतरा कम:। आप stdio करने के लिए स्विच और फ़ाइल मोड a+ है, जो शुरू से ही पढ़ता है और अंत में संलग्न कर देता है इस्तेमाल कर सकते हैं)

+0

चूंकि सी ++ 11, 'ios_base :: ऐप 'स्वयं ही अनुमति है, और" ए "के बराबर है। अद्यतन तालिका के लिए सी ++ 11 या सी ++ 14 में तालिका 132 देखें। –

3

मैं कैसे यह पूरा कर सकते हैं?

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

कि सरल नहीं है?

+0

"लेकिन मैं स्ट्रीम को पढ़ने/लिखने की स्थिति में रखना चाहता हूं।" –

+0

मैं स्वीकार करूंगा कि मुझे इस 'फ़ाइल प्रबंधक' वर्ग में बिंदु नहीं दिखाई देता है, लेकिन ओपी एक पढ़ना/लिखना स्ट्रीम चाहता है। –

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

खोलने के लिए है कि अगर मोड आप की आवश्यकता है मिलता है।

यदि यह अस्तित्व में नहीं है तो इसे पढ़ने/लिखने के लिए फ़ाइल खोलने का कोई जादू तरीका नहीं है, लेकिन अगर यह करता है तो इसे छोटा नहीं कर रहा है (इसकी सामग्री को हटा रहा है)। आपको इसे कई चरणों में करना है।

संबंधित मुद्दे