2008-11-05 16 views
94

असल में, मैं यह जांचना चाहता हूं कि मुझे वास्तव में इसे खोलने का प्रयास करने से पहले फ़ाइल खोलने का अधिकार है या नहीं; मैं इस चेक के लिए कोशिश/पकड़ का उपयोग नहीं करना चाहता जब तक कि मुझे नहीं करना चाहिए। क्या कोई फ़ाइल एक्सेस प्रॉपर्टी है जिसे मैं हाथ से देख सकता हूं?.NET में किसी फ़ाइल के लिए एक्सेस अस्वीकार कर दिया गया है, तो आप आसानी से कैसे जांच सकते हैं?

+2

कैप्शन जब मैंने टैग बदल दिया: "मैं सही कर रहा हूं"। कोई मजाक नहीं। –

+5

सहमत - मेरी इच्छा है कि एक TryOpen (यानी कोशिश-पार पैटर्न) थे। – Tristan

उत्तर

142

मैंने अतीत में यह अनगिनत बार किया है, और लगभग हर बार जब मैंने इसे किया है तो भी प्रयास करने में गलत था।

फ़ाइल अनुमतियां (यहां तक ​​कि फ़ाइल अस्तित्व) अस्थिर — वे किसी भी समय बदल सकते हैं। मर्फी के कानून के लिए धन्यवाद विशेष रूप से में फ़ाइल की जांच करते समय और जब आप इसे खोलने का प्रयास करते हैं तो बीच की संक्षिप्त अवधि शामिल होती है। यदि आप किसी ऐसे क्षेत्र में हैं जहां आपको पता है कि आपको पहले जांच करने की आवश्यकता है तो एक बदलाव भी अधिक संभावना है। फिर भी आश्चर्यजनक रूप से पर्याप्त यह आपके परीक्षण या विकास वातावरण में कभी नहीं होगा, जो काफी स्थिर हैं। इससे समस्या को बाद में ट्रैक करना मुश्किल हो जाता है और इस तरह के बग के उत्पादन में इसे आसान बनाता है।

इसका मतलब यह है कि यदि आपकी जांच के बावजूद फ़ाइल अनुमतियां या अस्तित्व खराब हैं, तो भी आपको अपवाद को संभालने में सक्षम होना चाहिए। अपवाद हैंडलिंग कोड आवश्यक है, चाहे आप पहले से ही फ़ाइल की अनुमतियों की जांच कर रहे हों या नहीं। अपवाद हैंडलिंग कोड अस्तित्व या अनुमति जांच की कार्यक्षमता के सभी प्रदान करता है। इसके अतिरिक्त, इस तरह के अपवाद हैंडलर धीमे होने के लिए जाने जाते हैं, यह याद रखना महत्वपूर्ण है कि डिस्क I/o धीमा है ... बहुत धीमा ... और .xists() फ़ंक्शन या चेकिंग अनुमतियों को कॉल करने से बल मिलेगा फाइल सिस्टम के बाहर अतिरिक्त यात्रा।

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

+3

बिल्कुल। यह दौड़ की स्थिति का एक उत्कृष्ट उदाहरण है। – Powerlord

+0

यदि "फाइल सिस्टम म्यूटेक्स" था तो यह बहुत अच्छा होगा। लेकिन इसके अस्तित्व के बिना, आप सही मर चुके हैं। –

+0

या लिनक्स/यूनिक्स, का प्रयोग करें। – chrissie1

3

एरिक Lippert शायद यही कारण है योएल सही here

+0

हेहे के बारे में बात कर रहे हैं, मैंने कुछ समय पहले पढ़ा था और इस सटीक पोस्ट के बारे में भी सोच रहा था, क्योंकि यह वास्तव में एक परेशान अपवाद है। लेकिन हम अभी भी एक अंतर्निहित फ़ाइल.TryOpen() विधि की प्रतीक्षा कर रहे हैं, और फिर भी आपको सावधान रहना होगा यदि आप पर्याप्त साझाकरण पहुंच की अनुमति देते हैं। –

3

सबसे पहले है, क्या योएल Coehoorn कहा।

इसके अलावा: आपको उन धारणाओं की जांच करनी चाहिए जो आपकी इच्छा को तब तक प्रयास/पकड़ने से बचने की इच्छा रखते हैं जब तक आपको यह करना न पड़े। तर्क से बचने के लिए सामान्य कारण जो अपवादों पर निर्भर करता है (Exception ऑब्जेक्ट्स खराब प्रदर्शन करता है) शायद फ़ाइल खोलने वाले कोड के लिए प्रासंगिक नहीं है।

मुझे लगता है कि यदि आप एक निर्देशिका लिख ​​रहे हैं जो List<FileStream> को निर्देशिका उपट्री में प्रत्येक फ़ाइल खोलकर पॉप्युलेट करता है और आपको उम्मीद है कि उनमें से बड़ी संख्या में पहुंच योग्य नहीं है तो आप फ़ाइल खोलने से पहले फ़ाइल अनुमतियां जांचना चाहेंगे कि आपको बहुत सारे अपवाद नहीं मिले। लेकिन आप अभी भी अपवाद को संभालेंगे। साथ ही, यदि आप एक ऐसा तरीका लिख ​​रहे हैं जो आपके द्वारा किया गया है तो शायद आपके प्रोग्राम के डिज़ाइन में कुछ गड़बड़ है। किसी और को एक समान समस्या के साथ यहाँ आने के लिए

21

त्वरित टिप:

ऐसे ड्रॉपबॉक्स के रूप में वेब तुल्यकालन क्षुधा से सावधान रहें। मैंने बस "उपयोग" कथन (पैटर्न का निपटान) सोचने में 2 घंटे बिताए हैं .NET में टूटा हुआ है।

मुझे अंत में एहसास हुआ कि ड्रॉपबॉक्स लगातार उन्हें सिंक करने के लिए पृष्ठभूमि में फ़ाइलों को पढ़ और लिख रहा है।

अनुमान लगाएं कि मेरा विजुअल स्टूडियो प्रोजेक्ट फ़ोल्डर कहां स्थित है? पाठ्यक्रम के "मेरा ड्रॉपबॉक्स" फ़ोल्डर के अंदर।

इसलिए जब मैंने डीबग मोड में अपना आवेदन चलाया, तो फ़ाइलों को पढ़ने और लिखने वाली फ़ाइलों को ड्रॉपबॉक्स द्वारा ड्रॉपबॉक्स सर्वर के साथ समन्वयित करने के लिए निरंतर उपयोग किया जा रहा था। इससे लॉकिंग/एक्सेस टकराव हुआ।

तो कम से कम अब मुझे पता है कि मुझे एक और अधिक मजबूत फ़ाइल ओपन फ़ंक्शन (यानी TryOpen() की आवश्यकता है जो कई प्रयास करेगा)। मुझे आश्चर्य है कि यह पहले से ही ढांचे का एक अंतर्निहित हिस्सा नहीं है।

[अपडेट]

यहाँ मेरी सहायक समारोह है:

/// <summary> 
/// Tries to open a file, with a user defined number of attempt and Sleep delay between attempts. 
/// </summary> 
/// <param name="filePath">The full file path to be opened</param> 
/// <param name="fileMode">Required file mode enum value(see MSDN documentation)</param> 
/// <param name="fileAccess">Required file access enum value(see MSDN documentation)</param> 
/// <param name="fileShare">Required file share enum value(see MSDN documentation)</param> 
/// <param name="maximumAttempts">The total number of attempts to make (multiply by attemptWaitMS for the maximum time the function with Try opening the file)</param> 
/// <param name="attemptWaitMS">The delay in Milliseconds between each attempt.</param> 
/// <returns>A valid FileStream object for the opened file, or null if the File could not be opened after the required attempts</returns> 
public FileStream TryOpen(string filePath, FileMode fileMode, FileAccess fileAccess,FileShare fileShare,int maximumAttempts,int attemptWaitMS) 
{ 
    FileStream fs = null; 
    int attempts = 0; 

    // Loop allow multiple attempts 
    while (true) 
    { 
     try 
     { 
      fs = File.Open(filePath, fileMode, fileAccess, fileShare); 

      //If we get here, the File.Open succeeded, so break out of the loop and return the FileStream 
      break; 
     } 
     catch (IOException ioEx) 
     { 
      // IOExcception is thrown if the file is in use by another process. 

      // Check the numbere of attempts to ensure no infinite loop 
      attempts++; 
      if (attempts > maximumAttempts) 
      { 
       // Too many attempts,cannot Open File, break and return null 
       fs = null; 
       break; 
      } 
      else 
      { 
       // Sleep before making another attempt 
       Thread.Sleep(attemptWaitMS); 

      } 

     } 

    } 
    // Reutn the filestream, may be valid or null 
    return fs; 
} 
+3

@Ash मुझे लगता है कि आपने ठीक से प्रश्न नहीं पढ़ा वह कोशिश पकड़ने से बचना चाहता है। – Ravisha

+8

@ रवीशा, क्या आपने जोएल के शीर्ष वोट दिए गए जवाब को भी पढ़ा? जैसा कि जोएल कहते हैं, ** "इसके बजाय आप फ़ाइल को खोलने की कोशिश करते हैं और अपवाद को संभालते हैं यदि यह विफल रहता है" **। कृपया केवल इसलिए मत डालें क्योंकि आपको इस तथ्य को पसंद नहीं है कि कुछ बचा नहीं जा सकता है। – Ash

+0

कोड के लिए धन्यवाद! एक बात, उदाहरण के लिए उपयोग करना बेहतर हो सकता है देखें [Tazeem उत्तर यहाँ] (http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/e99a7cea-43d3-49b1-82bc-5669e0b9d052) – Cel

-3
public static FileStream GetFileStream(String filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileShare, ref int attempts, int attemptWaitInMilliseconds) 
{    
    try 
    { 
     return File.Open(filePath, fileMode, fileAccess, fileShare); 
    } 
    catch (UnauthorizedAccessException unauthorizedAccessException) 
    { 
     if (attempts <= 0) 
     { 
      throw unauthorizedAccessException; 
     } 
     else 
     { 
      Thread.Sleep(attemptWaitInMilliseconds); 
      attempts--; 
      return GetFileStream(filePath, fileMode, fileAccess, fileShare, ref attempts, attemptWaitInMilliseconds); 
     } 
    } 
} 
+8

-1: "फेंक" का उपयोग करें; "अनधिकृत एक्सेस अपवाद;" नहीं फेंकें। आप अपना स्टैक ट्रेस खो रहे हैं। –

+0

रेफरी द्वारा 'प्रयासों' को पारित क्यों किया जाता है? इसका कोई अर्थ नही बन रहा है। न तो '==' की बजाय '<=' के लिए परीक्षण करता है। –

+1

@ जॉन: ठीक है, इस मामले में यह * वांछित * रिकर्सिव कॉल के गहरे घोंसले (गहरे घोंसले) स्टैक ट्रेस को खोने के लिए है, इसलिए मुझे लगता है कि इस उदाहरण में 'फेंक पूर्व' वास्तव में * सही काम है * करना। –

3

यहाँ इस आधार पर पढ़ने का एक नया अनुमति बनाता है समाधान आपके लिए

var fileIOPermission = new FileIOPermission(FileIOPermissionAccess.Read, 
              System.Security.AccessControl.AccessControlActions.View, 
              MyPath); 

if (fileIOPermission.AllFiles == FileIOPermissionAccess.Read) 
{ 
    // Do your thing here... 
} 

देख रहे है सभी फ़ाइलों के पथ के लिए देखें, फिर जांचता है कि यह फ़ाइल एक्सेस पढ़ने के बराबर है या नहीं।

+0

यह कोड डीआईआरएस पर झूठी नकारात्मकता देता है – Conrad

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