कारण क्या है?
त्रुटि संदेश बहुत स्पष्ट है: आप एक फ़ाइल का उपयोग करने का प्रयास कर रहे हैं, और यह सुलभ नहीं है क्योंकि एक अन्य प्रक्रिया (या यहां तक कि एक ही प्रक्रिया) इसके साथ कुछ कर रही है (और यह किसी भी साझाकरण की अनुमति नहीं देता)।
डिबगिंग
आपके विशिष्ट परिदृश्य के आधार पर इसे हल करना (या समझना बहुत कठिन) आसान हो सकता है। चलो कुछ देखते हैं।
आपकी प्रक्रिया उस फ़ाइल को एक्सेस करने के लिए केवल एक ही है
आप सुनिश्चित करें कि अन्य प्रक्रिया आपकी अपनी प्रक्रिया है। यदि आप जानते हैं कि आप उस फ़ाइल को अपने प्रोग्राम के किसी अन्य भाग में खोलते हैं, तो सबसे पहले आपको यह जाँचना होगा कि आप प्रत्येक उपयोग के बाद फ़ाइल हैंडल को ठीक से बंद कर दें। यहाँ इस बग के साथ कोड का एक उदाहरण दिया गया है:
var stream = new FileStream(path, FileAccess.Read);
var reader = new StreamReader(stream);
// Read data from this file, when I'm done I don't need it any more
File.Delete(path); // IOException: file is in use
सौभाग्य से FileStream
लागू होता है IDisposable
, इसलिए एक using
बयान के अंदर अपने सभी कोड को लपेटना आसान है :
using (var stream = File.Open("myfile.txt", FileMode.Open)) {
// Use stream
}
// Here stream is not accessible and it has been closed (also if
// an exception is thrown and stack unrolled
यह पैटर्न यह भी सुनिश्चित करेगा कि अपवाद के मामले में फ़ाइल को खुला नहीं छोड़ा जाएगा (यह कारण हो सकता है कि फ़ाइल उपयोग में है: कुछ गलत हो गया, और किसी ने इसे बंद नहीं किया; इस पोस्ट को देखें; उदाहरण के लिए को )।
यदि सब कुछ ठीक लगता है (आप निश्चित रूप से अपवाद के मामले में भी हमेशा आपके द्वारा खोली गई हर फ़ाइल को बंद करते हैं) और आपके पास कई काम करने वाले धागे हैं, तो आपके पास दो विकल्प हैं: फ़ाइल एक्सेस प्राप्त करने के लिए अपने कोड को फिर से काम करें (हमेशा करने योग्य नहीं और हमेशा नहीं चाहता था) या एक रिट्री पैटर्न लागू करें । यह आई / ओ संचालन के लिए एक बहुत ही सामान्य पैटर्न है: आप कुछ करने की कोशिश करते हैं और त्रुटि के मामले में आप प्रतीक्षा करते हैं और फिर से प्रयास करते हैं (क्या आपने खुद से पूछा है, उदाहरण के लिए, विंडोज शेल को आपको सूचित करने में कुछ समय लगता है कि एक फ़ाइल उपयोग में है और हटाया नहीं जा सकता?) C # में इसे लागू करना बहुत आसान है ( डिस्क I / O , नेटवर्किंग और डेटाबेस एक्सेस के बारे में बेहतर उदाहरण देखें )।
private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;
for (int i=1; i <= NumberOfRetries; ++i) {
try {
// Do stuff with file
break; // When done we can break loop
}
catch (IOException e) when (i <= NumberOfRetries) {
// You may check error code to filter some exceptions, not every error
// can be recovered.
Thread.Sleep(DelayOnRetry);
}
}
कृपया एक सामान्य त्रुटि पर ध्यान दें जो हम StackOverflow पर अक्सर देखते हैं:
var stream = File.Open(path, FileOpen.Read);
var content = File.ReadAllText(path);
इस स्थिति ReadAllText()
में विफल हो जाएगा क्योंकि फ़ाइल उपयोग में है ( File.Open()
पहले की पंक्ति में)। फाइल को पहले से खोलना न केवल अनावश्यक है बल्कि गलत भी है। एक ही सभी पर लागू होता है File
कार्यों है कि एक नहीं लौटते संभाल फ़ाइल आप काम कर रहे हैं: File.ReadAllText()
, File.WriteAllText()
, File.ReadAllLines()
, File.WriteAllLines()
और दूसरों (जैसे File.AppendAllXyz()
कार्यों) सभी खुले और बंद अपने आप फ़ाइल होगा।
आपकी प्रक्रिया उस फ़ाइल तक पहुँचने के
लिए एकमात्र नहीं है यदि आपकी प्रक्रिया उस फ़ाइल तक पहुँचने के लिए एकमात्र नहीं है, तो बातचीत कठिन हो सकती है। एक रिट्री पैटर्न में मदद मिलेगी (यदि फ़ाइल किसी और के द्वारा नहीं खोली जानी चाहिए लेकिन यह है, तो आपको एक उपयोगिता की आवश्यकता है कि प्रक्रिया एक्सप्लोरर जैसी जांच करें कि कौन क्या कर रहा है )।
बचने के तरीके
लागू होने पर, हमेशा फाइलों को खोलने के लिए बयानों का उपयोग करें। जैसा कि पिछले पैराग्राफ में कहा गया है, यह सक्रिय रूप से आपको कई सामान्य त्रुटियों से बचने में मदद करेगा ( इस पोस्ट को उदाहरण के लिए देखें कि इसका उपयोग कैसे न करें )।
यदि संभव हो, तो यह तय करने का प्रयास करें कि कौन विशिष्ट फ़ाइल तक पहुंच रखता है और कुछ प्रसिद्ध तरीकों के माध्यम से पहुंच को केंद्रीकृत करता है। यदि, उदाहरण के लिए, आपके पास एक डेटा फ़ाइल है जहां आपका प्रोग्राम पढ़ता है और लिखता है, तो आपको एक एकल वर्ग के अंदर सभी I / O कोड को बॉक्स करना चाहिए। यह डिबग को आसान बना देगा (क्योंकि आप हमेशा वहां एक ब्रेकपॉइंट डाल सकते हैं और देख सकते हैं कि कौन क्या कर रहा है) और यह भी कि एकाधिक एक्सेस के लिए यह सिंक्रोनाइज़ेशन पॉइंट (यदि आवश्यक हो) होगा।
भूल जाओ मैं / ओ संचालन हमेशा विफल हो सकता है, एक आम उदाहरण यह है:
if (File.Exists(path))
File.Delete(path);
अगर कोई फ़ाइल को File.Exists()
पहले लेकिन बाद में हटाता है File.Delete()
, तो यह एक IOException
ऐसी जगह फेंक देगा जहां आप गलत तरीके से सुरक्षित महसूस कर सकते हैं।
जब भी संभव हो, एक रिट्री पैटर्न लागू करें , और यदि आप उपयोग कर रहे हैं, तो FileSystemWatcher
कार्रवाई स्थगित करने पर विचार करें (क्योंकि आप अधिसूचित हो जाएंगे, लेकिन एक एप्लिकेशन अभी भी उस फ़ाइल के साथ विशेष रूप से काम कर सकता है)।
उन्नत परिदृश्य
यह हमेशा इतना आसान नहीं होता है, इसलिए आपको किसी और के साथ साझा करने की आवश्यकता हो सकती है। यदि, उदाहरण के लिए, आप शुरुआत से लेकर अंत तक पढ़ रहे हैं, तो आपके पास कम से कम दो विकल्प हैं।
1) FileStream
उचित सिंक्रनाइज़ेशन फ़ंक्शन के साथ समान साझा करें (क्योंकि यह थ्रेड-सुरक्षित नहीं है )। यह और यह देखें एक उदाहरण के लिए पदों।
2) FileShare
समान फ़ाइल को समान रूप से एक्सेस करने के लिए अन्य प्रक्रियाओं (या अपनी प्रक्रिया के अन्य भागों) की अनुमति देने के लिए ओएस को निर्देश देने के लिए गणना का उपयोग करें ।
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}
इस उदाहरण में मैंने दिखाया कि पढ़ने के लिए एक फ़ाइल कैसे खोलें और पढ़ने के लिए साझा करें; कृपया ध्यान दें कि जब पढ़ना और लिखना ओवरलैप होता है, तो इसका परिणाम अपरिभाषित या अमान्य डेटा होता है। यह एक ऐसी स्थिति है जिसे पढ़ते समय संभाला जाना चाहिए। यह भी ध्यान दें कि यह stream
थ्रेड-सेफ़ तक पहुंच नहीं बनाता है , इसलिए इस ऑब्जेक्ट को कई थ्रेड्स के साथ साझा नहीं किया जा सकता है जब तक कि एक्सेस किसी तरह से सिंक्रनाइज़ न हो (अन्य लिंक देखें)। अन्य साझाकरण विकल्प उपलब्ध हैं, और वे अधिक जटिल परिदृश्य खोलते हैं। अधिक जानकारी के लिए कृपया MSDN को देखें।
सामान्य एन प्रक्रियाओं में सभी एक साथ एक ही फ़ाइल से पढ़ सकते हैं, लेकिन केवल एक ही लिखना चाहिए, एक नियंत्रित परिदृश्य में आप समवर्ती लेखन को सक्षम कर सकते हैं लेकिन इस उत्तर के अंदर कुछ पाठ पैराग्राफ में इसे सामान्यीकृत नहीं किया जा सकता है।
क्या किसी अन्य प्रक्रिया द्वारा उपयोग की गई फ़ाइल को अनलॉक करना संभव है ? यह हमेशा सुरक्षित नहीं है और इतना आसान नहीं है लेकिन हां, यह संभव है ।