2012-09-25 13 views
6

मुझे डिस्क पर प्रोटोबफ डेटा संग्रहीत करने में कोई समस्या है। एप्लिकेशन मैंने सॉकेट पर डेटा स्थानांतरित करने के लिए प्रोटोकॉल बफर का उपयोग किया है (जो ठीक काम करता है), लेकिन जब मैं डिस्क को डेटा स्टोर करने का प्रयास करता हूं तो यह विफल हो जाता है। असल में, डेटा रिपोर्टों को सहेजने में कोई समस्या नहीं है, लेकिन मैं उन्हें फिर से लोड नहीं कर सकता। किसी भी सुझाव की खुशी से सराहना की जाएगी।प्रोटोकॉल बफर; डेटा को डिस्क में सहेजना और वापस समस्या को लोड करना

void writeToDisk(DataList & dList) 
{ 
    // open streams 
    int fd = open("serializedMessage.pb", O_WRONLY | O_CREAT); 
    google::protobuf::io::ZeroCopyOutputStream* fileOutput = new google::protobuf::io::FileOutputStream(fd); 
    google::protobuf::io::CodedOutputStream* codedOutput = new google::protobuf::io::CodedOutputStream(fileOutput); 

    // save data 
    codedOutput->WriteLittleEndian32(PROTOBUF_MESSAGE_ID_NUMBER); // store with message id 
    codedOutput->WriteLittleEndian32(dList.ByteSize()); // the size of the data i will serialize 
    dList.SerializeToCodedStream(codedOutput); // serialize the data 

    // close streams 
    delete codedOutput; 
    delete fileOutput; 

    close(fd); 
} 

मैंने इस फ़ंक्शन के अंदर डेटा सत्यापित किया है, डीएलआईस्ट में डेटा की अपेक्षा है। धाराओं की रिपोर्ट है कि कोई त्रुटि नहीं होती है, और डिस्क पर उचित बाइट्स लिखे गए थे। (फ़ाइल भी उचित आकार का है) लेकिन जब मैं डेटा को वापस पढ़ने की कोशिश करता हूं, तो यह काम नहीं करता है। इसके अलावा, वास्तव में अजीब बात यह है कि अगर मैं इस फ़ाइल में अधिक डेटा जोड़ता हूं, तो मैं पहले संदेश पढ़ सकता हूं (लेकिन अंत में एक नहीं)।

void readDataFromFile() 
{ 
    // open streams 
    int fd = open("serializedMessage.pb", O_RDONLY); 
    google::protobuf::io::ZeroCopyInputStream* fileinput = new google::protobuf::io::FileInputStream(fd); 
    google::protobuf::io::CodedInputStream* codedinput = new google::protobuf::io::CodedInputStream(fileinput); 

    // read back 
    uint32_t sizeToRead = 0, magicNumber = 0; 
    string parsedStr = ""; 

    codedinput->ReadLittleEndian32(&magicNumber); // the message id-number i expect 
    codedinput->ReadLittleEndian32(&sizeToRead); // the reported data size, also what i expect 
    codedinput->ReadString(&parsedstr, sizeToRead)) // the size() of 'parsedstr' is much less than it should (sizeToRead) 

    DataList dl = DataList(); 

    if (dl.ParseFromString(parsedstr)) // fails 
    { 
     // work with data if all okay 
    } 

    // close streams 
    delete codedinput; 
    delete fileinput; 
    close(fd); 
} 

स्पष्ट रूप से मैंने सब कुछ सरल बनाने के लिए यहां कुछ कोड छोड़े हैं। एक साइड नोट के रूप में मैंने एक स्ट्रिंग & को संदेश को क्रमबद्ध करने का भी प्रयास किया है जो उस स्ट्रिंग को कोडेडऑटपुटस्ट्रीम के माध्यम से सहेजता है। यह या तो काम नहीं करता है। मैंने हालांकि उस स्ट्रिंग की सामग्री को सत्यापित किया है, इसलिए मुझे लगता है कि अपराधी स्ट्रीम फ़ंक्शन होना चाहिए।

यह एक विंडोज वातावरण है, सी ++ प्रोटोकॉल बफर और क्यूटी के साथ।

आपके समय के लिए धन्यवाद!

+0

आप 'नए' का उपयोग क्यों कर रहे हैं और स्पष्ट रूप से विनाशकों को बुला रहे हैं? इस बात का कोई भी मतलब नहीं है। –

+0

मैंने इस समस्या को ठीक करने के लिए संपादित किया है। मुझे नहीं पता कि उस समय ऐसा क्यों अच्छा विचार था। अच्छा पकड़, लेकिन मेरी समस्या को ठीक करने के लिए पर्याप्त नहीं है। – almagest

+0

आप वास्तव में केवल आधा मुद्दा तय करते हैं: पॉइंटर्स और 'नया' का उपयोग करके अभी भी कोई समझ नहीं आता है। लेकिन हाँ, यह आपकी समस्या से संबंधित होने की संभावना नहीं है। –

उत्तर

4

मैंने फ़ाइल डिस्क्रिप्टर से fstream में स्विच करके और FileCopyStream को OstreamOutputStream में स्विच करके इस समस्या को हल किया।

हालांकि मैंने पूर्व का उपयोग करने वाले उदाहरण देखे हैं, यह मेरे लिए काम नहीं करता है।

मुझे Google coded_stream शीर्षलेख में छिपा हुआ एक अच्छा कोड उदाहरण मिला। link #1

इसके अलावा, क्योंकि मुझे प्रोटोकॉल बफर का उपयोग करके एक ही फ़ाइल में एकाधिक संदेशों को क्रमबद्ध करने की आवश्यकता है, यह लिंक प्रबुद्ध था। link #2

किसी कारण से, आउटपुट फ़ाइल 'पूर्ण' नहीं है जब तक कि मैं वास्तव में स्ट्रीम ऑब्जेक्ट्स को निर्वहन नहीं करता।

-1

ReadString

की

codedinput->readRawBytes इनसीड और

ParseFromString

प्रोटोकॉल बफ़र्स साथ बहुत परिचित नहीं लेकिन ReadString के बजाय dl.ParseFromArray उपयोग करने के लिए केवल प्रकार strine के एक क्षेत्र को पढ़ सकता है की कोशिश करो।

+0

अच्छा विचार , लेकिन इसके परिणामस्वरूप पहले जैसा ही व्यवहार था। – almagest

2

पढ़ने विफलता थी क्योंकि फ़ाइल O_BINARY के साथ पढ़ने के लिए नहीं खोला गया था - यह करने के लिए परिवर्तन फ़ाइल खोलने और यह काम करता है:

int fd = open("serializedMessage.pb", O_RDONLY | O_BINARY);

मूल कारण यहां के रूप में ही है: "read() only reads a few bytes from file"। प्रोटोबफ प्रलेखन में एक उदाहरण के बाद आप बहुत अधिक संभावना रखते थे जो फ़ाइल को उसी तरह खोलता है, लेकिन यह फ़ाइल में विशेष चरित्र को हिट करते समय विंडोज पर पार्सिंग रोकता है।

इसके अलावा, लाइब्रेरी के हाल के संस्करणों में, आप पढ़ने के आकार + पेलोड जोड़े को सरल बनाने के लिए protobuf::util::ParseDelimitedFromCodedStream का उपयोग कर सकते हैं।

... प्रश्न प्राचीन हो सकता है, लेकिन समस्या अभी भी मौजूद है और यह उत्तर लगभग निश्चित रूप से मूल समस्या का समाधान है।

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