2012-12-04 10 views
17

मुझे कस्टम ओस्ट्रीम को कार्यान्वित करने के तरीके को समझने के लिए कुछ मार्गदर्शन या पॉइंटर्स चाहिए। मेरी आवश्यकताएं हैं:एक कस्टम ओस्ट्रीम

  1. कई डेटा प्रकारों के लिए '< <' ऑपरेटर वाला एक वर्ग।
  2. उद्देश्य डेटाबेस को आउटपुट भेजना है। प्रत्येक "रेखा" को एक अलग रिकॉर्ड में जाना चाहिए।
  3. प्रत्येक रिकॉर्ड सबसे महत्वपूर्ण फ़ील्ड टेक्स्ट (या ब्लॉब) होगा, लेकिन समय, आदि जैसे कुछ अन्य क्षेत्रों को स्वचालित रूप से
  4. बफरिंग महत्वपूर्ण है, क्योंकि मैं डेटाबेस में नहीं जाना चाहता हर रिकॉर्ड।

सबसे पहले, क्या यह ओस्ट्रीम से प्राप्त करने लायक है? ओस्ट्रीम से प्राप्त करके मुझे क्या मिलता है? क्या होगा यदि मेरी कक्षा बस कुछ operator<< विधियों (कुछ कस्टम डेटा प्रकारों सहित) लागू करती है। ओस्ट्रीम से मुझे कौन सी कार्यक्षमता मिलती है?

मान लीजिए कि मैं जो चाहता हूं वह ओस्ट्रीम से ली गई कक्षा है, मुझे ओस्ट्रीम और स्ट्रीमबफ कक्षाओं के बीच संबंधों को समझने के लिए कुछ मार्गदर्शन की आवश्यकता है। मुझे किसको लागू करने की आवश्यकता है? कुछ नमूनों को देखते हुए, ऐसा प्रतीत होता है कि मुझे ओस्ट्रीम से प्राप्त करने की आवश्यकता नहीं है, और केवल ओस्ट्रीम कन्स्ट्रक्टर को एक कस्टम स्ट्रीमबफ दें। क्या यह सच है? क्या कैनोलिक दृष्टिकोण है?

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

यदि स्ट्रीमबफ से व्युत्पन्न कस्टम क्लास आवश्यक है, तो क्या स्ट्रीमबफ से सीधे स्ट्रिंगबफ (या किसी अन्य वर्ग) से प्राप्त कोई लाभ होगा?

"लाइनों" के लिए। मैं कम से कम जब 'एंडल' मैनिपुलेटर का उपयोग कर कक्षा के अपने उपयोगकर्ताओं को एक नई लाइन (यानी डेटाबेस में रिकॉर्ड) होना चाहता हूं। शायद - प्रयास पर निर्भर करता है - प्रत्येक '\ n' चरित्र को भी एक नया रिकॉर्ड माना जाना चाहिए। मेरे कस्टम ओस्ट्रीम और/या स्ट्रीमबफ प्रत्येक के लिए अधिसूचित कौन है?

+2

आपको शायद अपनी खुद की 'स्ट्रीमबफ' कक्षा बनाना चाहिए, जो सभी भारी कामों को संभालता है, और फिर एक बहुत ही सरल 'ओस्ट्रीम' वर्ग बनाता है जो 'std :: basic_ostream' प्राप्त करता है और अपने' स्ट्रीमबफ 'ऑब्जेक्ट के साथ स्वयं को प्रारंभ करता है। –

+4

आपको [बूस्ट.इस्ट्रीम] (http://www.boost.org/doc/libs/release/libs/iostreams/doc/index.html) देखना चाहिए - यह कस्टम स्ट्रीम और बफर को बहुत आसान बना देता है। –

+0

आपके संपादन के लिए धन्यवाद, @ मार्कसपाकर – Uri

उत्तर

15

ओस्ट्रीम के लिए एक कस्टम गंतव्य का अर्थ है अपने ओस्ट्रीमबफ को लागू करना। यदि आप अपने स्ट्रीमबफ को वास्तव में बफर करना चाहते हैं (यानी प्रत्येक चरित्र के बाद डेटाबेस से कनेक्ट नहीं होते हैं), तो ऐसा करने का सबसे आसान तरीका std::stringbuf से विरासत प्राप्त करने वाला वर्ग बनाना है। केवल फ़ंक्शन जिसे आपको ओवरराइड करने की आवश्यकता होगी sync() विधि है, जिसे स्ट्रीम स्ट्रीम होने पर भी कहा जा रहा है।

class MyBuf : public std::stringbuf 
{ 
public: 
    virtual int sync() { 
     // add this->str() to database here 
     // (optionally clear buffer afterwards) 
    } 
}; 

फिर आप एक std::ostream अपने बफर का उपयोग कर बना सकते हैं:

MyBuf buff; 
std::ostream stream(&buf) 

अधिकांश लोगों को एक डेटाबेस के लिए धारा पुनः निर्देशित के खिलाफ की सलाह दी है, लेकिन वे मेरी वर्णन डेटाबेस मूल रूप से एक भी ब्लॉब क्षेत्र जहां है कि ध्यान नहीं दिया सभी पाठ जा रहे हैं। दुर्लभ मामलों में, मैं एक अलग क्षेत्र में डेटा भेज सकता हूं। यह मेरी स्ट्रीम द्वारा समझा कस्टम गुणों के साथ सुविधा प्रदान की जा सकती है। उदाहरण के लिए:

blob: 'Some text more text' 
process_id: 1234 

process_id() एक संरचना ProcessID लौटने एक विधि है:

MyStream << "Some text " << process_id(1234) << "more text" << std::flush 

उपर्युक्त कोड डेटाबेस में एक रिकार्ड बनाएगा। फिर, मेरे ओस्ट्रीम के कार्यान्वयन में, मेरे पास operator<<(ProcessID const& pid) है, जो प्रक्रिया आईडी को तब तक संग्रहीत करता है जब तक यह लिखा न जाए। बहुत अच्छा काम करता है!

+0

संपादन के लिए @JDW धन्यवाद (इसे मैन्युअल रूप से फिर से करना था)। – Uri

+0

क्या आपकी 'माइस्ट्रीम' कक्षा 'std :: ostream' से प्राप्त होती है? क्या यह किसी भी तरीके को ओवरराइड करता है? मैं यह पूछ रहा हूं क्योंकि मुझे यह कहते हुए एक त्रुटि मिल रही है कि कन्स्ट्रक्टर सुरक्षित है –

+0

"बफर साफ़ करने" के लिए सबसे अच्छा तरीका यह है कि यह-> str ("") ' – jtbr

18

सबसे आसान तरीका std::streambuf वारिस के लिए और सिर्फ दो तरीकों को ओवरराइड है:

  • std::streamsize xsputn(const char_type* s, std::streamsize n) - अपने आंतरिक बफर, उदाहरण के लिए std::string लिए प्रदान की जाती आकार के साथ किसी दिए गए बफर संलग्न करने के लिए;
  • int_type overflow(int_type c) - अपने आंतरिक बफर में एक char जोड़ने के लिए।

आपका स्ट्रीमबफ जो भी आप चाहते हैं (उदाहरण के लिए डीबी कनेक्शन) से बनाया जा सकता है। आंतरिक बफर में कुछ जोड़ने के बाद आप इसे लाइनों में विभाजित करने और डीबी में कुछ धक्का देने की कोशिश कर सकते हैं (या बस बाद में निष्पादित करने के लिए SQL कथन बफर करें)।

इसका उपयोग करने के लिए: बस अपने streambuf को किसी भी std::ostream पर कन्स्ट्रक्टर का उपयोग करके संलग्न करें।

सरल! मैंने syslog पर स्ट्रिंग आउटपुट करने के लिए ऐसा कुछ किया है - उपयोगकर्ता परिभाषित कक्षाओं के लिए किसी भी कस्टम operator<< के साथ सब कुछ ठीक काम करता है।

+2

xsputn को streambuf के सभी उद्देश्यों को हराने के लिए लागू नहीं करेगा? फ़ाइलबफ और स्ट्रिंगबफ दोनों इस विधि को ओवरराइड नहीं करते हैं, लेकिन केवल अतिप्रवाह (जिसे स्ट्रिंगबफ द्वारा बुलाया जाता है)। – Uri

+0

असल में केवल अतिप्रवाह विधि अतिप्रवाह होना है। डिफ़ॉल्ट रूप से sputn प्रत्येक चरित्र पर sputc निष्पादित करता है। – DawidPi

4

my2c - मुझे लगता है कि आप इसे गलत तरीके से निपट रहे हैं। एक स्ट्रीम एक अच्छा विचार की तरह लग सकती है, लेकिन आपको पंक्ति के अंत को इंगित करने के लिए एक तरीका भी चाहिए (और फिर अगर कोई भूल जाता है तो क्या होगा?) मैं जावा तैयार किए गए स्टेटमेंट्स और बैचों के काम के तरीके के साथ कुछ सुझाव दूंगा विधियों का एक सेट प्रदान करते हैं जो प्रकार और कॉलम इंडेक्स को स्वीकार करते हैं, फिर एक "बैच" विधि जो स्पष्ट रूप से यह स्पष्ट करती है कि आप वास्तव में उस पंक्ति को बैच कर रहे हैं और फिर बैच को धक्का देने के लिए निष्पादित करते हैं।

कोई स्ट्रीम आधारित ऑपरेशन किस प्रकार कॉलम भरने के लिए इंगित करने के लिए प्रकार (आमतौर पर) पर भरोसा करेगा - लेकिन यदि आपके पास दो इन्स हैं तो क्या होगा? उपयोगकर्ता के रूप में आईएमओ, यह डेटाबेस में रिकॉर्ड डालने का एक प्राकृतिक तरीका नहीं लगता है ...

1

iostreams तंत्र में चरित्र इनपुट/आउटपुट का नया स्रोत या गंतव्य जोड़ने के लिए, आपको एक नया बनाना चाहिए streambuf कक्षा। स्ट्रीम बफर कक्षाओं का कार्य 'बाहरी डिवाइस' के साथ संवाद करना है जो पात्रों को संग्रहित करेगा और बफरिंग सुविधाएं प्रदान करेगा।

आपके डेटाबेस के साथ संवाद करने के लिए iostreams का उपयोग करने में समस्या यह है कि डेटाबेस तालिका किसी चरित्र अनुक्रम की अवधारणा से मेल नहीं खाती है। एक वर्ग छेद में एक गोल peg धक्का जैसे थोड़ा सा। एक streambuf केवल वर्णों पर काम करता है। यह एकमात्र चीज है जिसे कभी प्रस्तुत किया गया है। इसका मतलब है कि streambuf को फ़ील्ड ढूंढने और विभाजक रिकॉर्ड करने के लिए प्रस्तुत किए गए चरित्र स्ट्रीम को पार्स करना होगा। यदि आप इस मार्ग पर जाने का निर्णय लेते हैं, तो मैं भविष्यवाणी करता हूं कि आप इसे streambuf में सीएसवी-टू-एसक्यूएल कनवर्टर लिखने के लिए तैयार करेंगे।

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

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