2010-01-12 17 views
13

में कक्षा के ऑब्जेक्ट को लिखें और पढ़ें I C++ में बाइनरी फ़ाइल में और कक्षा से ऑब्जेक्ट लिखने और पढ़ने की कोशिश करते हैं। मैं अलग-अलग डेटा सदस्य नहीं लिखना चाहता हूं लेकिन पूरे ऑब्जेक्ट को एक बार लिखना चाहता हूं।द्विआधारी फ़ाइल

class MyClass { 
public: 
    int i; 

    MyClass(int n) : i(n) {} 
    MyClass() {} 

    void read(ifstream *in) { in->read((char *) this, sizeof(MyClass)); } 
    void write(ofstream *out){ out->write((char *) this, sizeof(MyClass));} 
}; 

int main(int argc, char * argv[]) { 
    ofstream out("/tmp/output"); 
    ifstream in("/tmp/output"); 

    MyClass mm(3); 
    cout<< mm.i << endl; 
    mm.write(&out); 

    MyClass mm2(2); 
    cout<< mm2.i << endl; 
    mm2.read(&in); 
    cout<< mm2.i << endl; 

    return 0; 
} 

चल उत्पादन बताते हैं कि mm.i का मूल्य माना जाता है कि बाइनरी फ़ाइल के लिए लिखा पढ़ा नहीं है और सही ढंग से आवंटित किया mm2.i को हालांकि

$ ./main 
3 
2 
2 

तो क्या गलत है: एक साधारण उदाहरण के लिए इसके साथ?

मुझे आमतौर पर किसी बाइनरी फ़ाइल में या किसी वर्ग के किसी ऑब्जेक्ट को लिखने या पढ़ने के बारे में क्या पता होना चाहिए?

उत्तर

11

डेटा buffered किया जा रहा है, इसलिए जब आप इसे पढ़ने के लिए वास्तव में फ़ाइल तक नहीं पहुंचे हैं। चूंकि आप इन/आउट फ़ाइल को संदर्भित करने के लिए दो अलग-अलग ऑब्जेक्ट्स का उपयोग करते हैं, इसलिए ओएस ने यह नहीं बताया है कि वे कैसे संबंधित हैं।

mm.write(&out); 
out.flush() 

या फ़ाइल बंद (जो एक अंतर्निहित फ्लश करता है):

mm.write(&out); 
out.close() 

तुम भी वस्तु बाहर जाना होने से फ़ाइल को बंद कर सकते हैं

आप या तो फ़ाइल फ्लश करने के लिए की जरूरत है स्कोप:

int main() 
{ 
    myc mm(3); 

    { 
     ofstream out("/tmp/output"); 
     mm.write(&out); 
    } 

    ... 
} 
+0

धन्यवाद! क्या सी ++ में फ़ाइल लेखन और पढ़ने दोनों के लिए एक ऑब्जेक्ट को परिभाषित करना संभव है? मुझे याद है कि सी – Tim

+0

@ टिम में यह संभव है।हां, आपके पास पढ़ने और लिखने के लिए एक फ़ाइल-स्ट्रीम खोला जा सकता है। –

+0

मेरी राय में, यान रामिन का जवाब बहुत उपयोगी है। वह इस flushing विचार बताते हैं, और बढ़ावा के साथ बेहतर तरीका भी इंगित करता है। – MeM

1

मेरा सी ++ सुंदर जंग और अत्यधिक परीक्षण किया गया है, लेकिन आप सीरियलाइजेशन और अनसराइलाइजेशन पर एक नज़र डालना चाहेंगे। FAQ

9

कच्चे डेटा को डंप करना एकाधिक कोणों से एक भयानक विचार है। पॉइंटर डेटा जोड़ने के बाद यह और भी बदतर हो जाएगा।

एक सुझाव Boost.Serialization का उपयोग करना होगा जो कहीं अधिक मजबूत डेटा डंपिंग की अनुमति देता है।

आपकी मुख्य समस्या यह है कि फ़ाइल में अभी तक fstream buffering के कारण सामग्री शामिल नहीं है। फ़ाइल को बंद या फ्लश करें।

2

मैं प्रतिध्वनि करूंगा "आपको यह नहीं करना चाहिए"। यदि आप ऊपर दिए गए कोड में sizeof(myc) प्रिंट करते हैं, तो संभवत: 4 की उम्मीद है, लेकिन आप उम्मीद कर सकते हैं ... लेकिन पढ़ने को बदलने और वर्चुअल होने के लिए लिखने का प्रयास करें। जब मैंने ऐसा किया, तो यह आकार 16 के रूप में प्रिंट करता है। उन 12 बाइट संवेदनशील मूल्यों के साथ आंतरिक गड़बड़ हैं — और उन्हें सहेजते हुए और फिर उन्हें वापस पढ़ने के लिए एक पॉइंटर मान अभी भी अच्छा होने की उम्मीद की तरह होगा यदि आपने इसे लिखा और लोड किया यह फिर से।

यदि आप सीरियलाइजेशन को बाधित करना चाहते हैं और सी ++ ऑब्जेक्ट मेमोरी सीधे डिस्क पर मैप करना चाहते हैं, तो उसे हैक करने के तरीके हैं। लेकिन नियम शामिल हैं और यह दिल की बेहोशी के लिए नहीं है। एक उदाहरण के रूप में POST++ (Persistent Object Storage for C++) देखें।

मैं जोड़ूंगा कि आपने fail() या eof() स्थिति की जांच नहीं की है। यदि आप जानते थे कि आप fstream API का दुरुपयोग कर रहे थे। इसे फिर से आज़माएं:

void read(ifstream *in) { 
    in->read((char *) this, sizeof(myc)); 
    if (in->fail()) 
     cout << "read failed" << endl; 
} 
void write(ofstream *out){ 
    out->write((char *) this, sizeof(myc)); 
    if (out->fail()) 
     cout << "write failed" << endl; 
} 

... और देखें कि क्या होता है।

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