2009-12-09 17 views
22

यह बहुत आम होना चाहिए, लेकिन मुझे यह आकर्षक लगता है कि मुझे कोई सीधा आगे समाधान नहीं मिला।सी ++ एसएलएल स्ट्रिंगस्ट्रीम प्रत्यक्ष बफर एक्सेस

मूल रूप से मैंने नेटवर्क पर एक स्ट्रिंगस्ट्रीम में एक फ़ाइल में पढ़ा।

std::stringstream membuf(std::ios::in | std::ios::out | std::ios::binary); 

अब मैं कुछ सी पुस्तकालय है कि स्मृति के पढ़ने हिस्सा तक सीधी पहुंच चाहता है: यह घोषणा है। मैं इसे कैसे प्राप्त करूं? केवल पढ़ने के लिए ठीक है पढ़ें। सी समारोह पूरा होने के बाद, मैं मेमोरीस्ट्रीम का निपटान करता हूं, इसके लिए कोई आवश्यकता नहीं है।

str() बफर की प्रतिलिपि बनाता है, जो अनावश्यक लगता है और स्मृति को दोगुना करता है।

क्या मुझे कुछ याद आ रही है? शायद एक अलग एसटीएल वर्ग बेहतर काम करेगा।

संपादित करें: जाहिर है, स्ट्रिंगस्ट्रीम को लगातार संग्रहित करने की गारंटी नहीं है। क्या है?

यदि मैं vector<char> का उपयोग करता हूं तो मैं बाइट बफर कैसे प्राप्त करूं?

+0

चूंकि 'वेक्टर' अपने सभी तत्वों को संगत रूप से संग्रहीत करता है, इसलिए आप "बफर" प्राप्त कर सकते हैं: 'char * buffer = & vector_char.front();' –

+1

@ स्टेव गुइडी: जब तक आप नहीं जानते कि कितने बाइट जा रहे हैं नेटवर्क से बाहर आते हैं, एक 'वेक्टर ' 'std: stringstream' से अधिक प्रतियां बना सकता है क्योंकि यह स्टोरेज को संगत रखने के लिए इसके डेटा को पुन: आवंटित करने और कॉपी करने के लिए _has_ को कॉपी करता है। –

+0

क्या यह मदद करता है: http://stackoverflow.com/questions/132358/how-to-read-file-content-into-istringstream/138645#138645 –

उत्तर

7

आप std :: string वापस पाने के लिए str() पर कॉल कर सकते हैं। वहां से char* प्राप्त करने के लिए आप std :: string पर c_str() पर कॉल कर सकते हैं। ध्यान दें कि c_str() सरकारी तौर पर इस प्रयोग के लिए समर्थित नहीं है, लेकिन हर किसी इसे इस तरह :)

संपादित

यह शायद एक बेहतर समाधान है का उपयोग करता है: std::istream::read। उस पृष्ठ पर उदाहरण से:

buffer = new char [length]; 

    // read data as a block: 
    is.read (buffer,length); 
+5

मैन, बफर को तीन गुना कर रहा है। – Kugel

+1

हालांकि यह काम करता है। यदि एसटीएल में कोई बेहतर तरीका नहीं है तो मैं इसे उत्तर के रूप में चिह्नित करूंगा। – Kugel

+2

'c_str()' 'std :: basic_string' के मानक इंटरफ़ेस का हिस्सा है। मामूली विस्तार के अलावा कि यह 'const char *' (और प्रश्न केवल पढ़ने के लिए पूछे जाने पर पूछता है) देता है, 'c_str' का यह उपयोग किस प्रकार समर्थित नहीं है? –

11

std::stringstream नहीं है (जरूरी) ने अपने बफर समीप की दुकान लेकिन हिस्सा आवंटित कर सकते हैं के रूप में यह धीरे-धीरे भर जाता है। यदि आप इसके सभी डेटा को स्मृति के एक संगत क्षेत्र में चाहते हैं तो आपको इसकी प्रतिलिपि बनाना होगा और यही वह है जो str() आपके लिए करता है।

बेशक, यदि आप एक अलग भंडारण रणनीति के साथ कक्षा का उपयोग या लिखना चाहते हैं तो आप कर सकते हैं, लेकिन आपको std::stringstream का उपयोग करने की आवश्यकता नहीं है।

+0

चार्ल्स, क्या आप मेरी मदद कर सकते हैं? मुझे पता है कि मैं स्ट्रिंगस्ट्रीम द्वारा 'rdbuf()' के साथ अंतर्निहित स्ट्रिंगबफ प्राप्त कर सकता हूं। और मुझे मानक कहने में शब्द नहीं मिल रहा है कि स्ट्रिंगबफ/स्ट्रिंगस्ट्रीम गैर-संगत हो सकता है। मैं किसी भी पॉइंटर्स की सराहना करता हूं जो आप दे सकते हैं। धन्यवाद। –

+0

कहां कहता है कि 'स्ट्रिंगबफ' को संगत भंडारण का उपयोग करना है? मानक को अंतर्निहित चरित्र अनुक्रम को स्टोर करने की आवश्यकता होती है लेकिन यह निर्दिष्ट नहीं करता है कि कैसे। 'स्ट्रीमबफ' इंटरफेस में 'ओवरफ्लो' और 'अंडरफ्लो' है, इसलिए स्ट्रीम को एक ही संगत रेंज के रूप में उपलब्ध कराने की आवश्यकता नहीं होती है और केवल अन्य आवश्यकताएं 'std :: string' और 'str' ओवरलोड से कन्स्ट्रक्टर हैं) जो सभी अंतर्निहित चरित्र अनुक्रम की प्रतियों के साथ सौदा करते हैं। मैं किसी भी कार्यान्वयन से निराश (हल्के से) निराश होता हूं जो हमेशा संगत भंडारण का उपयोग करता है क्योंकि इंटरफ़ेस को वृद्धिशील परिशिष्टों के लिए डिज़ाइन किया गया है। –

+1

rdbuf मैंने परीक्षण किए गए सभी परीक्षण मामलों में ठीक काम किया है ... लेकिन अगर मैं आप थे तो मैं इसका उपयोग करने से पहले कुछ संगतता परीक्षण (rdbuf = धाराओं में वर्णों की संख्या) पर जोर देना चाहूंगा। अपने टेस्ट सूट में चिपकाएं और प्लेटफ़ॉर्म पोर्टिंग आदि के लिए जाना अच्छा है। –

6

ठीक है, अगर आप भंडारण के बारे में गंभीर रूप से चिंतित हैं, तो आप धातु के करीब आ सकते हैं। basic_stringstream एक विधि, rdbuf() जो रिटर्न यह basic_stringbuf (जो basic_streambuf से ली गई है) है है। इसके बाद आप ईबैक(), egptr(), और gptr() पॉइंटर्स का उपयोग सीधे बफर से बाहर वर्णों तक पहुंचने के लिए कर सकते हैं। मैंने अपने वांछित अर्थशास्त्र के साथ कस्टम बफर को लागू करने के लिए अतीत में इस मशीनरी का उपयोग किया है, इसलिए यह सक्षम है।

सावधान रहें, यह दिल की बेहोशी के लिए नहीं है! कुछ दिनों को अलग करें, Standard C++ IOStreams and Locales, या समान नाइटपीकी संदर्भ पढ़ें, और सावधान रहें ...

+0

'eback', 'egptr' और' gptr' संरक्षित हैं इसलिए' stringbuf' के लिए 'rdbuf' पॉइंटर प्राप्त करने वाला नहीं है आपको इन तक पहुंच प्रदान करें। यहां तक ​​कि अगर ऐसा होता है, तो मुझे नहीं लगता कि यह _guaranteed_ है कि आप '.str() 'और' .data() 'की कम प्रतियों के साथ अंतर्निहित अनुक्रम की एक संगत प्रति बना सकते हैं। –

+0

ठीक है। चूंकि मैं अपना खुद का व्युत्पन्न बफर लागू कर रहा था, इसलिए मैं विधियों तक पहुंच सकता था। और मुझे लगता है कि जी ++ बस संगत पहुंच करता है। मुझे अभी भी मानक में इस प्रतिबंध (गैर-संगत) नहीं मिल सका ... –

12

आप stringstream

stringstream membuf(std::ios::in | std::ios::out | std::ios::binary); 
membuf.rdbuf(yourVeryOwnStreamBuf); 

आपका अपना बफर basic_streambuf से प्राप्त किया जाना चाहिए में अपने आप को बफ़र लिखने और है कि बफर का उपयोग करके इस्तेमाल किया बफर का पूरा नियंत्रण ले, और उचित रूप से sync() और overflow() तरीकों ओवरराइड कर सकते हैं।

आपके आंतरिक प्रतिनिधित्व के लिए आप शायद vector<char>, और reserve() जैसे किसी आवश्यक आकार के लिए उपयोग कर सकते हैं ताकि कोई पुनर्वितरण और प्रतियां नहीं की जा सकें।

इसका तात्पर्य है कि आपको पहले से आवश्यक स्थान के लिए ऊपरी बाउंड पता है। लेकिन अगर आप पहले से आकार को नहीं जानते हैं, और अंत में एक आकस्मिक बफर की आवश्यकता है, प्रतियां निश्चित रूप से अपरिहार्य हैं।

+1

रीलॉक आपको पहले स्थान आवंटन को बढ़ाने की कोशिश करके प्रतिलिपि बनाकर बफर विकसित करने की अनुमति देता है। realloc अक्सर डेटा ले जाता है, लेकिन समय के 100% नहीं। मैंने पाया है कि यह "प्रतिलिपि हमेशा" से कहीं अधिक कुशल है। वेक्टर से प्राप्त करने के बजाय, बस अपने कस्टम स्ट्रीम क्लास के आधार के रूप में एक char * और realloc का उपयोग करें। –

+0

मैं आलसी दिखाई दूंगा, लेकिन यह एक प्रश्न है जो पूर्ण स्निपेट के साथ उत्तर के रूप में वर्णित बिल्कुल अवधारणा के उत्तर के रूप में उत्तर के लायक होगा। मुझे एक बार 'basic_streambuf' विरासत में मिला और मैं इसे एक और बार नहीं करूँगा, क्षमा करें। – ceztko

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