2010-10-15 15 views
8

मुझे पता है कि यह मूर्खतापूर्ण प्रतीत हो सकता है, लेकिन अगर मैं फ़ाइल बंद करता हूं तो निम्न कोड केवल तभी काम करता है? अगर मैं फ़ाइल बंद नहीं करता हूं, तो पूरी स्ट्रीम लिखी नहीं जाती है।मुझे सी # में एक फ़ाइल क्यों बंद करनी चाहिए?

कदम:

  1. भागो प्रपत्र लोड पर इस कोड।
  2. माउस प्रदर्शित करने के बाद माउस का उपयोग बंद करें।
  3. कार्यक्रम समाप्त हो जाता है।

क्या फ़ाइल ऑब्जेक्ट को स्कोप से बाहर होने पर स्वचालित रूप से फ़्लश या बंद नहीं किया जाना चाहिए? मैं सी # के लिए नया हूं, लेकिन मैं सी ++ विनाशकों में बंद() को कॉल जोड़ने के लिए उपयोग किया जाता हूं।

// Notes: complete output is about 87KB. Without Close(), it's missing about 2KB at the end. 

// Convert to png and then convert that into a base64 encoded string. 
string b64img = ImageToBase64(img, ImageFormat.Png); 
// Save the base64 image to a text file for more testing and external validation. 
StreamWriter outfile = new StreamWriter("../../file.txt"); 
outfile.Write(b64img); 
// If we don't close the file, windows will not write it all to disk. No idea why 
// that would be. 
outfile.Close(); 
+5

आप http://blogs.msdn.com/b/oldnewthing/archive/ पर चर्चा मिल सकता है 2010/08/10/10048150.aspx सी # और सी ++ के बीच अंतर के लिए स्पष्टीकरण और औचित्य प्रदान करने में सहायक होने के लिए सहायक हो। आम तौर पर, मैं सी ++ विनाशकों की तुलना सी # 'आईडीस्पोजेबल 'और' {{'' का उपयोग करके करूंगा। और निश्चित रूप से, 'उपयोग' को 'बंद करें' या 'निपटान' को स्पष्ट रूप से कॉल करने से सुरक्षित है, क्योंकि यह ऑब्जेक्ट का निपटारा सुनिश्चित करने के लिए 'प्रयास-अंत में' ब्लॉक में कॉल को लपेटता है। – Brian

+0

धन्यवाद, सभी, स्पष्ट और त्वरित सहायता के लिए। – Harvey

उत्तर

21

सी # में स्वचालित निर्धारिक सफाई नहीं है। यदि आप इसे चलाने पर नियंत्रण करना चाहते हैं तो आपको क्लीनअप फ़ंक्शन को कॉल करना सुनिश्चित करना होगा। using ब्लॉक ऐसा करने का सबसे आम तरीका है।

यदि आप स्वयं को क्लीनअप में नहीं डालते हैं, तो सफाई तब होती है जब कचरा कलेक्टर किसी अन्य चीज़ के लिए स्मृति की आवश्यकता होती है, जो बहुत लंबे समय बाद हो सकती है।

using (StreamWriter outfile = new StreamWriter("../../file.txt")) { 
    outfile.Write(b64img); 
} // everything is ok, the using block calls Dispose which closes the file 

संपादित करें: हार्वे बताते हैं, जबकि सफाई जब वस्तु एकत्र हो जाता है का प्रयास किया जाएगा के रूप में, इस सफलता के किसी भी गारंटी नहीं है। परिपत्र संदर्भों के साथ समस्याओं से बचने के लिए, रनटाइम "दाएं" क्रम में ऑब्जेक्ट को अंतिम रूप देने का कोई प्रयास नहीं करता है, इसलिए FileStreamStreamWriter फ़ाइनलाइज़र रन के समय वास्तव में पहले से ही मर सकता है और buffered आउटपुट को फ्लश करने का प्रयास करता है।

आप वस्तुओं सफाई की जरूरत है कि, यह स्पष्ट रूप से करते हैं, या तो साथ using (स्थानीय रूप से-दायरे के उपयोग के लिए) या (जैसे वर्ग के सदस्यों की referents रूप में लंबे समय के लिए रहने वाले वस्तुओं के लिए) IDisposable.Dispose फोन करके में सौदा है।

+1

को बंद करने की आवश्यकता नहीं है, किसी भी समय जब आप किसी ऑब्जेक्ट को नोटिस करते हैं जो 'आईडीस्पोजेबल' लागू करता है, तो आपको 'उपयोग' का उपयोग करना चाहिए, जब तक कि आप ऑब्जेक्ट नहीं करना चाहते तुरंत साफ हो जाएं (उदाहरण के लिए यदि यह एक सदस्य चर है, तो आप बाद में 'इसका निपटान' करना चाहेंगे)। – Brian

+0

कल्पना करें कि सी ++ सबकुछ साफ कर रहा है ... डरावनी – Spooks

+0

मुझे लगता है कि मुझे गार्ड से पकड़ा गया है कि क्लीनअप फ़ंक्शन ** कभी नहीं ** ** जब तक मैं बंद नहीं करता हूं। ऐसा लगता है कि जब मैं कार्यक्रम को समाप्त करता हूं, किसी भी आवश्यकता-से-निपटान-वस्तुओं पर सफाई चलाने की बजाय, यह कचरा संग्रह के बिना समाप्त हो जाता है। – Harvey

8

क्योंकि लिखें() buffered है और बफर स्पष्ट रूप से बंद() द्वारा फ़्लश किया गया है।

+1

या फ्लश() के लिए एक स्पष्ट कॉल द्वारा। –

+2

कि देशी फ़ाइल हैंडल को बंद करने की आवश्यकता है आईएमओ अधिक महत्वपूर्ण है। विशेष रूप से जब तक यह अंतिम रूप से चलने तक फ़ाइल को लॉक कर सकता है। – CodesInChaos

1

ओएस को बेहतर प्रदर्शन करने के लिए ऑपरेटिंग सिस्टम कैश ब्लॉक डिवाइस पर लिखने के लिए लिखें। आप autoflush करने के लिए streamwriter सेट करने के लिखने के बाद बफर flushing द्वारा एक लिखने के लिए मजबूर करते हैं।

+0

अभी भी फ़ाइल को बंद नहीं करता है, और अधिकांश प्रोग्राम इसे तब तक नहीं खोल सकते जब तक कि पहला प्रोग्राम इसे बंद न करे। –

+1

हाँ मेरा बिंदु उस लेख को मजबूर करना था जिसे आपको – rerun

3

स्ट्रीम ऐसी वस्तुएं हैं जो गैर-कचरा एकत्रित संसाधनों को "प्रबंधित" या "संभाल" देती हैं। इसलिए (स्ट्रीम) इसलिए आईडीस्पोजेबल इंटरफ़ेस को कार्यान्वित करते हैं, जब 'उपयोग' के साथ उपयोग किया जाता है, तो सुनिश्चित होगा कि गैर-कचरा एकत्रित संसाधन साफ़ हो जाएंगे। इसे आजमाएं:

using (StreamWriter outfile = new StreamWriter("../../file.txt")) 
{ 
    outfile.Write(b64img); 
} 

# क्लोज़ के बिना, आप सुनिश्चित नहीं हो सकते कि अंतर्निहित फ़ाइल हैंडल ठीक से बंद हो जाएगा। कभी-कभी, यह ऐप शटडाउन पर हो सकता है।

+0

धन्यवाद, यह कुछ भ्रम को दूर करने में मदद करता है। मेरे मामले में, फ़ाइल हैंडल ** कभी भी बंद नहीं हुआ ** ऐप शटडाउन पर भी बंद था। (इस अर्थ में बंद है कि एक स्पष्ट बंद() फ्लश होगा) – Harvey

+0

आपका स्वागत है। – DevSolo

-2

क्योंकि सी # डिजाइनर जावा क्लोनिंग कर रहे थे और नाम के बावजूद सी ++ नहीं थे।

मेरी राय में वे वास्तव में नाव से चूक गए। स्कोप निकास पर सी ++ स्टाइल विनाश बहुत बेहतर होगा।

इसे स्मृति को बेहतर होने के लिए भी रिलीज़ नहीं करना पड़ेगा, केवल स्वचालित रूप से फ़ाइनलाइज़र या आईडीस्पोजेबल विधि को चलाएं।

+2

-1: त्रुटिपूर्ण भाषा के बारे में शिकायत वास्तव में सहायक नहीं है, विशेष रूप से शिकायतें जैसे "सी # जावा की एक प्रति है और यही कारण है कि यह जावा की तरह काम करता है।" यह एक जानबूझकर डिजाइन निर्णय था, और यह बताता है कि कैसे कचरा संग्रह सी # में काम करता है। स्वचालित निपटान काम नहीं करेगा क्यों एक स्पष्टीकरण के लिए http://blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048150.aspx देखें। – Brian

+1

मैं वह नहीं हूं जो डाउनवॉटेड है, लेकिन 6k प्रतिनिधि पर, आपको पता होना चाहिए कि अब तक टिप्पणियां कैसे छोड़ें। यह एक जवाब नहीं है। बीटीडब्ल्यू जो आप चाहते हैं वह मौजूद है, इसे सी ++/सीएलआई, आरएआईआई के साथ .NET समर्थन और दायरे के अंत में विनाशक को स्वचालित कॉल कहा जाता है। –

+1

कक्षा सी {स्ट्रीम एस; शून्य एम() {एस एस 2 = ओपनएएसट्रीम(); यह.s = एस 2; }} - आपका विचार यह है कि जब s2 गुंजाइश से बाहर हो जाता है, तो धारा स्वचालित रूप से निपटाई जानी चाहिए, भले ही इस.s में कोई संदर्भ है? क्या आपको नहीं लगता कि लोगों के लिए आश्चर्यजनक होगा? –

2

क्योंकि आप एक स्ट्रीमराइटर का उपयोग कर रहे हैं और यह Close() लेखक तक बफर को फ्लश नहीं करता है। आप निर्दिष्ट कर सकते हैं कि आप लेखक को हर बार लिखने के लिए लिखना चाहते हैं जब आप AutoFlush स्ट्रीमराइटर की संपत्ति को सही पर सेट करके लिखते हैं।

दस्तावेज़ देखें। http://msdn.microsoft.com/en-us/library/system.io.streamwriter.aspx

आप "समापन" के बिना एक फाइल करने के लिए लिखना चाहते हैं, तो मैं प्रयोग करेंगे:

System.IO.File 
संबंधित मुद्दे