रूबी की File.open और f.close की आवश्यकता


92

अधिकांश प्रोग्रामिंग भाषाओं में यह सामान्य ज्ञान है कि फाइलों के साथ काम करने के लिए प्रवाह खुला-उपयोग-बंद है। फिर भी मैंने कई बार रूबी कोड में बेजोड़ फाइल देखी। कॉल्स और ज्ञान के इस रत्न को मैंने पाया कि माणिक डॉक्स:

कचरा कलेक्टर द्वारा दावा किए जाने पर I / O धाराएँ स्वतः बंद हो जाती हैं।

डार्कएरंडेलो फ्रेंडली irc इस मुद्दे पर लेते हैं:
[१ yes :१२ ] हाँ, और भी, फ़ाइल डिस्क्रिप्टर की संख्या आमतौर पर ओएस द्वारा सीमित होती है
[१ ]:२ ९] मुझे लगता है कि आप आसानी से उपलब्ध फ़ाइल डिस्क्रिप्टर से बाहर निकल सकते हैं इससे पहले कि कचरा इकट्ठा करने वाले कलेक्टर को देखें। यूपी। इस स्थिति में, आप उन्हें स्वयं बंद करना चाह सकते हैं। "कचरा कलेक्टर द्वारा दावा किया गया।" इसका मतलब है कि GC भविष्य में किसी बिंदु पर कार्य करता है। और यह महंगा है। फ़ाइलों को स्पष्ट रूप से बंद करने के कई कारण हैं।

  1. क्या हमें स्पष्ट रूप से बंद होने की आवश्यकता है
  2. यदि हाँ, तो जीसी ऑटोक्लोसे क्यों करता है?
  3. यदि नहीं तो विकल्प क्यों?

1
आपका 'सामान्य ज्ञान' पुराना हो चुका है क्योंकि विध्वंसक का आविष्कार किया गया था।
meagar

1
@meager: जब विनाशकों का आविष्कार किया गया था?
एंड्रयू ग्रिम

बस एक नोट: जबकि फ़ाइल विवरण सीमित हैं, लिनक्स पर कम से कम, सीमा काफी अधिक है।
Linuxios

1
@Linuxios: मेरे ubuntu12.04 पर $ ulimit -n => 1024यह केवल तभी उच्च होता है जब आप कुछ सरल कार्य करते हैं। बुरी आदत एक दिन बड़ी समस्या का कारण बनेगी!
एचवीएनएस ट्विटिंग

जवाबों:


133

मैंने कई बार रूबी कोड में बेजोड़ File.openकॉल्स देखीं

क्या आप एक उदाहरण दे सकते हैं? मैं केवल कभी-कभी यह देखता हूं कि न्यूबॉय द्वारा लिखे गए कोड में "अधिकांश प्रोग्रामिंग भाषाओं में सामान्य ज्ञान की कमी है जो फाइलों के साथ काम करने के लिए प्रवाह खुला-उपयोग-बंद है"।

अनुभवी रूबिस्ट या तो स्पष्ट रूप से अपनी फ़ाइलों को बंद कर देते हैं, या, अधिक मुहावरेदार रूप से File.open, ब्लॉक रूप का उपयोग करते हैं , जो आपके लिए फ़ाइल को स्वचालित रूप से बंद कर देता है। इसका कार्यान्वयन मूल रूप से कुछ इस तरह दिखता है:

def File.open(*args, &block)
  return open_with_block(*args, &block) if block_given?
  open_without_block(*args)
end

def File.open_without_block(*args)
  # do whatever ...
end

def File.open_with_block(*args)
  yield f = open_without_block(*args)
ensure
  f.close
end

अनुलेख एक विशेष मामला है। लिपियों में आम तौर पर इतने कम भाग होते हैं, और कुछ फ़ाइल विवरणों का उपयोग करते हैं कि यह बस उन्हें बंद करने के लिए समझ में नहीं आता है, क्योंकि ऑपरेटिंग सिस्टम स्क्रिप्ट बंद होने पर उन्हें वैसे भी बंद कर देगा।

क्या हमें स्पष्ट रूप से बंद होने की आवश्यकता है?

हाँ।

यदि हाँ, तो जीसी ऑटोक्लोसे क्यों करता है?

क्योंकि इसके द्वारा ऑब्जेक्ट को एकत्रित करने के बाद, आपके पास अब फ़ाइल को बंद करने का कोई रास्ता नहीं है, और इस प्रकार आप फ़ाइल डिस्क्रिप्टर को लीक कर देंगे।

ध्यान दें कि यह कचरा संग्रहकर्ता नहीं है जो फाइलों को बंद कर देता है। कचरा संग्रहकर्ता किसी वस्तु को इकट्ठा करने से पहले उसे अंतिम रूप से क्रियान्वित करता है। यह सिर्फ इतना होता है कि Fileवर्ग एक फाइनल को परिभाषित करता है जो फ़ाइल को बंद कर देता है।

यदि नहीं तो विकल्प क्यों?

क्योंकि व्यर्थ स्मृति सस्ता है, लेकिन बर्बाद फ़ाइल विवरणकर्ता नहीं हैं। इसलिए, यह किसी फ़ाइल डिस्क्रिप्टर के जीवनकाल को कुछ समय के लिए याद रखने के लिए समझ में नहीं आता है।

आप बस अनुमान नहीं लगा सकते जब कचरा कलेक्टर चलेंगे। तुम भी अनुमान नहीं लगा सकते , तो यह चलेंगे सब पर : यदि आप कभी नहीं स्मृति से बाहर चलाने, कचरा कलेक्टर कभी नहीं चलेंगे, इसलिए finalizer चलाने कभी नहीं होगा, इसलिए फ़ाइल को बंद किया जा कभी नहीं होगा।


1
github.com/isaac/sunspot/blob/cell/sunspot/lib/sunspot/… 13: (हालांकि इसका कर्नेल # खुला है और इसका मुख्य रूप से HTTP पक्ष के लिए उपयोग किया जाता है, लेकिन मैं इसे एक स्थानीय फ़ाइल पथ पैरामीटर के साथ फिर भी पहुँचा। ..; मैं अभी भी पैच एंड रिक्वेस्ट- पुलिंग ), github.com/jnicklas/carrierwave Ctrl + f "File.open" के लिए समय निकालने की कोशिश कर रहा हूं (यह एक उदाहरण के रूप में दिया गया है, लेकिन एक बुरे तरीके से ...), और कई अन्य जगहों पर मुझे याद नहीं है। मुझे अपनी परियोजनाओं में स्थिरता की आवश्यकताओं के कारण इस मुद्दे के साथ एक गोमांस है ..
clyfe

3
इस उदाहरण में, बचाव ब्लॉक के अंदर उठाना चाहिए? क्या यह सिर्फ़ एक रनटाइम त्रुटि नहीं है अगर उठाना कहा जाता है और कोई अपवाद नहीं है?
जेफ मंजरी

@ जेफस्टोरी: अच्छा कैच! 17 महीने किसी का ध्यान नहीं गया ...
Jörg W Mittag

@ JörgWMittag और अब 17 और महीने तय नहीं किए गए हैं: PI का अनुमान है कि यहां मुख्य बिंदु है ensure, rescueऔर raiseयह बिल्कुल भी आवश्यक नहीं है।
KL-7

मुझे लगता है कि आपके ensureबिना नहीं हो सकता rescue। और आप केवल चुपचाप अपवाद को निगल नहीं सकते हैं, आपको फ़ाइल बंद करने के बाद, इसे कॉलर को प्रचारित करने की आवश्यकता है। वैसे भी, मुझे मई '15 में फिर से याद दिलाइए :-D
Jörg W Mittag

71

आपको हमेशा उपयोग के बाद फाइल डिस्क्रिप्टर को बंद कर देना चाहिए, इससे फ्लश भी होगा। अक्सर लोग फ़ाइल डिस्क्रिप्टर को जीवन भर संभालने के लिए ब्लॉक के साथ File.open या समकक्ष पद्धति का उपयोग करते हैं । उदाहरण के लिए:

File.open('foo', 'w') do |f|
    f.write "bar"
end

उस उदाहरण में फ़ाइल स्वचालित रूप से बंद है।


अच्छी बात। मैंने बग को एक स्क्रिप्ट पर ट्रैक किया, जो File.close को कॉल नहीं करता है। परिणामस्वरूप अंतिम पंक्ति अब और फिर कुछ फाइलों में गायब हो जाएगी।
एरवान लीग्रैंड

बकाया। मुझे यह तरकीब कभी पता नहीं थी। उस संबंध में बहुत कुछ जावा -8 जैसा है। धन्यवाद।
सग्निता

2

Http://ruby-doc.org/core-2.1.4/File.html#method-c-open के अनुसार

कोई संबंधित ब्लॉक के साथ, File.open :: new का पर्याय है। यदि वैकल्पिक कोड ब्लॉक दिया गया है, तो इसे एक लॉजिक के रूप में खोली गई फ़ाइल को पास किया जाएगा और ब्लॉक समाप्त होने पर फ़ाइल ऑब्जेक्ट स्वचालित रूप से बंद हो जाएगा। ब्लॉक का मान File.open से लौटाया जाएगा।

इसलिए, ब्लॉक समाप्त होने पर स्वचालित रूप से बंद हो जाएगा : डी


1
  1. हाँ
  2. यदि आप ऐसा नहीं करते हैं, या कुछ अन्य विफलता है
  3. 2 देखें।

-3

हम File.read()रूबी में फ़ाइल को पढ़ने के लिए फ़ंक्शन का उपयोग कर सकते हैं ..... जैसे,

file_variable = File.read("filename.txt")

इस उदाहरण file_variableमें उस फ़ाइल का पूरा मूल्य हो सकता है ...।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.