यदि .NET में किसी फ़ाइल के लिए पहुँच अस्वीकृत है तो आप आसानी से कैसे देख सकते हैं?


100

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


2
कैप्शन जब मैंने टैग बदला: "im करेक्टिंग"। कोई मजाक नहीं।
जोएल कोएहॉर्न

6
सहमत- काश एक ट्रायपोन (यानी ट्राय-पार्स पैटर्न) होता।
ट्रिस्टन

जवाबों:


157

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

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

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

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


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

3
कोरो: आपको वैसे भी विफलता पर खराब अनुमतियों को संभालने में सक्षम होना चाहिए, और यह प्रारंभिक चेक को अनावश्यक और बेकार बनाता है।
जोएल कोएहॉर्न

2
एक प्रारंभिक जांच सामान्य विशिष्ट त्रुटियों को इनायत से संभालने में मदद कर सकती है - आगे की तलाश विशिष्ट कारणों के लिए विशेष अपवाद विशेषताओं के मिलान की तुलना में अक्सर आसान होती है। कोशिश / पकड़ अभी भी अनिवार्य है।
पीटरचेन

5
यह उत्तर इस सवाल का जवाब नहीं देता है कि "कैसे जांचने का अधिकार है कि मेरे पास फ़ाइल खोलने का अधिकार है" किसी उदाहरण से पहले इसे खोलने की कोशिश न करें। मामला बहुत अच्छी तरह से हो सकता है, कि यदि उस समय अनुमति की अनुमति नहीं है, तो सॉफ़्टवेयर फ़ाइल को पढ़ने का प्रयास नहीं करेगा, भले ही अनुमति की जाँच के बाद ही अनुमति बहुत अच्छी तरह से दी जा सकती है।
त्रिवेंको

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

25

इसी तरह की समस्या के साथ किसी और के लिए त्वरित टिप:

ड्रॉपबॉक्स जैसे वेब सिंक्रोनाइज़ेशन ऐप के लिए देखें। मैं सिर्फ 2 घंटे यह सोचकर बिताता हूं कि "स्टेटमेंट" (डिस्पोजल पैटर्न) का उपयोग .NET में टूट गया है।

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

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

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

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

[अपडेट करें]

यहाँ मेरा सहायक कार्य है:

/// <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
@ मुझे लगता है कि आप ठीक से पढ़े गए सवाल पर सवाल नहीं उठाते।
रविशा

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

कोड के लिए धन्यवाद! एक बात, उदाहरण के लिए Tazeem उत्तर यहाँ
Cel

यह देखते हुए कि आप फाइलस्ट्रीम को लौटाते हैं तो usingकॉलर द्वारा उपयोग किया जाना होगा ...
Cel

@Cel - usingयहाँ काम नहीं करेगा। उपयोग ब्लॉक के अंत में, fsजबरन बंद कर दिया जाएगा। आप कॉलर को एक बंद (इतना बेकार) फाइलस्ट्रीम देंगे!
टूलमेकरसेव

4

यहां वह उपाय है जिसकी आपको तलाश है

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

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

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


3

सबसे पहले, जोएल कोएहॉर्न ने क्या कहा।

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

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


-1
public static bool IsFileLocked(string filename)
        {
            bool Locked = false;
            try
            {
                FileStream fs =
                    File.Open(filename, FileMode.OpenOrCreate,
                    FileAccess.ReadWrite, FileShare.None);
                fs.Close();
            }
            catch (IOException ex)
            {
                Locked = true;
            }
            return Locked;
        }

-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: "फेंक" का उपयोग करें "अनधिकृत असफलता को न फेंकें"। आप अपने स्टैक ट्रेस खो रहे हैं।
जॉन सॉन्डर्स

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

1
@ जॉन: इस मामले में, यह (गहरी नेस्टेड) ​​रिकर्सिव कॉल के स्टैक ट्रेस को खोने के लिए वांछनीय है, इसलिए मुझे लगता है कि इस उदाहरण throw exमें वास्तव में सही काम करना है।
कोनराड रुडोल्फ

2
@Konrad: @Rudzitis: मैं -1 के लिए अपना कारण बदल रहा हूं। यह "थ्रो एक्स" द्वारा स्टैक को खराब करने से भी बदतर है। आप एक समय में पुनरावृत्ति के माध्यम से अतिरिक्त स्टैक स्तरों को कृत्रिम रूप से प्रेरित करके स्टैक को पेंच कर रहे हैं जब स्टैक गहराई वास्तव में मायने रखती है। यह पुनरावृत्ति समस्या है, पुनरावर्ती नहीं।
जॉन सॉन्डर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.