क्या आप एक ऐसे ऑब्जेक्ट की तलाश कर रहे हैं जो IO ऑब्जेक्ट (फाइल्स, सॉकेट्स, आदि) की तरह व्यवहार करता है, लेकिन जिसे आप स्ट्रिंग की तरह नियंत्रित कर सकते हैं?
तब StringIO आपके लिए है।
मैं आपको कुछ उदाहरण और ध्यान रखने योग्य चीजें दिखाता हूं!
बुनियादी उदाहरण
StringIO ऑब्जेक्ट बनाने के लिए आप यह कर सकते हैं:
io = StringIO.new("abc") फिर आप gets, read और each_line जैसे मेथड्स का उपयोग करके इस ऑब्जेक्ट से पढ़ सकते हैं।
मैंने आपके लिए सबसे उपयोगी मेथड्स के साथ एक आसान तालिका बनाई है:
| मेथड | विवरण |
|---|---|
| gets | इनपुट की एक लाइन पढ़ें |
| read | बाइट्स की एक विशिष्ट मात्रा पढ़ें (डिफ़ॉल्ट रूप से सभी) |
| each_line | एक ब्लॉक दिए जाने पर, प्रत्येक लाइन पर पुनरावृति करें |
| each_char | एक ब्लॉक दिए जाने पर, प्रत्येक कैरेक्टर पर पुनरावृति करें |
| << | डेटा जोड़ें |
| rewind | आंतरिक स्थिति पॉइंटर को रीसेट करें |
| string | StringIO ऑब्जेक्ट से एक वास्तविक स्ट्रिंग लौटाता है |
ध्यान दें कि StringIO में एक स्थिति पॉइंटर होता है।
यह पॉइंटर ट्रैक रखता है कि आपने कितने बाइट्स पढ़े हैं, बिल्कुल एक फाइल ऑब्जेक्ट की तरह।
इसलिए हर बार जब आप gets या read जैसे मेथड को कॉल करते हैं तो यह आपको उतना डेटा देगा और पॉइंटर को आगे बढ़ाएगा।
यहां तक कि map या each_line जैसे Enumerable मेथड्स भी स्थिति पॉइंटर को आगे बढ़ाएंगे, इसलिए इसे ध्यान में रखें।
io.each_line { |line| puts line } आप rewind मेथड का उपयोग करके स्थिति पॉइंटर को शुरुआत में रीसेट कर सकते हैं:
io.pos # 45 io.rewind io.pos # 0
बस इतना ही बुनियादी बातों के लिए।
मैं आपको StringIO के कुछ व्यावहारिक उपयोग दिखाने जा रहा हूं, लेकिन पहले मुझे आपको कुछ और दिखाना है।
StringScanner का क्या?
अब आपने देखा कि StringIO क्या कर सकता है, लेकिन रूबी स्टैंडर्ड लाइब्रेरी में एक और स्ट्रिंग-संबंधित क्लास शामिल है।
वह क्लास StringScanner है।
यह भ्रमित करने वाला हो सकता है क्योंकि उनके नाम और मेथड्स समान हैं, लेकिन आइए मुझे अंतर देखने में आपकी मदद करने दें।
मुख्य बात यह है:
एक StringIO ऑब्जेक्ट दूसरे IO ऑब्जेक्ट (जैसे File या Socket) को प्रतिस्थापित कर सकता है, लेकिन StringScanner पार्सिंग जैसी चीजों के लिए है (कुछ टेक्स्ट को टोकन के सेट में तोड़कर उसका अर्थ निकालना)।
उनके नाम में "स्ट्रिंग" होने के अलावा ये दो क्लास अभी भी कुछ साझा करते हैं, वे दोनों एक आंतरिक स्थिति पॉइंटर का उपयोग करते हैं।
स्टैंडर्ड इनपुट और आउटपुट को प्रतिस्थापित करना
मान लें कि आप एक कमांड-लाइन एप्लिकेशन लिख रहे हैं जो Kernel#gets मेथड का उपयोग करके उपयोगकर्ता से आउटपुट मांगता है...
...यदि आप इस कोड को टेस्ट करना चाहते हैं तो आपको हर बार हाथ से कुछ इनपुट करना होगा।
तो क्या स्वचालित टेस्टिंग तस्वीर से बाहर है?
नहीं, ऐसा नहीं है!
यहीं StringIO बचाव के लिए आता है। आप अपने टेस्ट इनपुट के साथ एक StringIO ऑब्जेक्ट इनिशियलाइज़ कर सकते हैं और फिर $stdin द्वारा इंगित स्टैंडर्ड इनपुट ऑब्जेक्ट को प्रतिस्थापित कर सकते हैं (यह वह जगह है जहां रूबी देखता है जब आप gets कॉल करते हैं)।
उदाहरण:
io = StringIO.new("input") $stdin = io gets # input इस तकनीक का उपयोग puts जैसे मेथड्स से आउटपुट कैप्चर करने के लिए भी किया जा सकता है।
डिस्प्ले मेथड्स डिफ़ॉल्ट आउटपुट डिवाइस पर प्रिंट करते हैं, जिसे 'स्टैंडर्ड आउटपुट' के रूप में जाना जाता है। रूबी में यह एक IO ऑब्जेक्ट द्वारा दर्शाया जाता है जिसे आप अपने StringIO ऑब्जेक्ट से प्रतिस्थापित कर सकते हैं।
उदाहरण:
io = StringIO.new("") $stdout = io # Print to $stdout puts "Jesus Castello is from Spain & likes to help people learn Ruby." # Restore original value $stdout = STDOUT io.rewind io.read # "Jesus Castello is from Spain & likes to help people learn Ruby." यह इनपुट संस्करण की तुलना में अधिक शामिल है, क्योंकि हम मूल STDOUT ऑब्जेक्ट को बहाल करना सुनिश्चित करना चाहते हैं और अपने StringIO को रिवाइंड करना चाहते हैं ताकि हम आउटपुट पढ़ सकें।
ध्यान दें कि अधिकांश टेस्टिंग फ्रेमवर्क्स में आपके लिए ऐसा करने के लिए एक मेथड शामिल होता है (Minitest के लिए assert_output और RSpec में आउटपुट मैचर), लेकिन यह जानना हमेशा बहुत अच्छा होता है कि पर्दे के पीछे क्या हो रहा है 🙂
सारांश
आपने StringIO क्लास के बारे में सीखा, जो एक वास्तविक IO ऑब्जेक्ट का अनुकरण करता है ताकि यह उस तरह के ऑब्जेक्ट के प्रतिस्थापन के रूप में कार्य कर सके।
यह उन क्लासेस को टेस्ट करने के लिए उपयोगी हो सकता है जो स्क्रीन पर आउटपुट लिखते हैं या टर्मिनल के माध्यम से उपयोगकर्ता इनपुट की आवश्यकता होती है।
यदि आप StringIO के कुछ दिलचस्प उपयोग जानते हैं तो हमें कमेंट्स में बताएं और इस लेख को शेयर करना न भूलें ताकि अधिक लोग इसका आनंद ले सकें!