अगर विंडोज के तहत एक दी गई स्ट्रिंग एक कानूनी / वैध फ़ाइल नाम है, तो मैं कैसे जांचूं?


165

मैं अपने आवेदन में एक बैच फ़ाइल का नाम बदलने की कार्यक्षमता शामिल करना चाहता हूं। एक उपयोगकर्ता एक गंतव्य फ़ाइल नाम पैटर्न टाइप कर सकता है और (पैटर्न में कुछ वाइल्डकार्ड्स को बदलने के बाद) मुझे यह जांचने की आवश्यकता है कि क्या यह विंडोज के तहत एक कानूनी फ़ाइल नाम होने जा रहा है। मैंने नियमित अभिव्यक्ति का उपयोग करने की कोशिश की है, [a-zA-Z0-9_]+लेकिन इसमें कई भाषाओं से कई राष्ट्रीय-विशिष्ट वर्ण शामिल नहीं हैं (जैसे umlauts और इतने पर)। ऐसा चेक करने का सबसे अच्छा तरीका क्या है?


यदि आप Regex के साथ किसी भी उत्तर का उपयोग करने जा रहे हैं, तो मैं एक स्थिर संकलित Regex का उपयोग करने का सुझाव देता हूं
AMissico

जवाबों:


100

आप Path.GetInvalidPathCharsऔर से अमान्य वर्णों की सूची प्राप्त कर सकते हैं GetInvalidFileNameChars

UPD: नियमित रूप से अभिव्यक्ति में इनका उपयोग करने के बारे में स्टीव कूपर का सुझाव देखें ।

UPD2: ध्यान दें कि MSDN में रिमार्क्स अनुभाग के अनुसार "इस पद्धति से लौटाया गया सरणी में वर्णों का पूरा सेट शामिल करने की गारंटी नहीं है जो फ़ाइल और निर्देशिका नामों में अमान्य हैं।" छहपत्रावली द्वारा प्रदान किया गया उत्तर अधिक विवरण में जाता है।


11
यह प्रश्न का उत्तर नहीं देता है; ऐसे कई तार हैं जिनमें केवल मान्य वर्ण (जैसे "....", "CON", सैकड़ों वर्ण लंबे तार) शामिल हैं जो वैध फ़ाइल नाम नहीं हैं।
डोर हाई आर्क

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

@ हाई आर्क: प्रश्न का उत्तर "सी # में देखें कि फ़ाइल नाम संभवतः मान्य है (यह मौजूद नहीं है)"। (हालांकि कुछ चतुर लोगों ने इस सवाल को इस एक के पक्ष में बंद कर दिया ...)
मिमीम्म्म्म

129

MSDN के "फ़ाइल या निर्देशिका का नामकरण" करने से , विंडोज के अंतर्गत एक कानूनी फ़ाइल नाम क्या है , इसके लिए सामान्य सम्मेलन हैं:

आप वर्तमान कोड पृष्ठ में किसी भी वर्ण का उपयोग कर सकते हैं (यूनिकोड / ANSI 127 से ऊपर), को छोड़कर:

  • < > : " / \ | ? *
  • वर्ण जिनका पूर्णांक निरूपण 0-31 (ASCII स्थान से कम) है
  • कोई अन्य वर्ण जो लक्ष्य फ़ाइल सिस्टम को अनुमति नहीं देता (कहते हैं, अनुगामी अवधि या स्थान)
  • डॉस नामों में से कोई भी: CON, PRN, AUX, NUL, COM0, COM1, COM3, COM3, COM4, ​​COM5, COM6, COM7, COM8, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT4, LPT5, LPT6, LPT7, LPT7, LPT8, LPT9 (और AUX.txt, आदि से बचें)
  • फ़ाइल का नाम सभी अवधि है

जाँच करने के लिए कुछ वैकल्पिक बातें:

  • फ़ाइल पथ (फ़ाइल नाम सहित) में 260 से अधिक वर्ण नहीं हो सकते हैं (जो \?\उपसर्ग का उपयोग नहीं करते हैं )
  • यूनिकोड फ़ाइल पथ (फ़ाइल नाम सहित) का उपयोग करते समय 32,000 से अधिक वर्णों के साथ \?\(ध्यान दें कि उपसर्ग निर्देशिका घटकों का विस्तार कर सकता है और इसका कारण 32,000 सीमा से अधिक हो सकता है)

8
आरक्षित फ़ाइलनामों को शामिल करने के लिए +1 - जो पिछले उत्तरों में छूट गए थे।
SqlRyan

2
यदि आप "\\? \" वाक्यविन्यास का उपयोग करते हैं तो "AUX" पूरी तरह से प्रयोग करने योग्य फ़ाइल नाम है। बेशक, ऐसे प्रोग्राम जो उस वाक्य रचना का उपयोग नहीं करते हैं, उनके साथ काम करने में वास्तविक समस्याएं हैं ... (XP पर परीक्षण किया गया)
user9876

9
ऊपर उल्लिखित इन सभी स्थितियों के लिए सही रेगेक्स निम्नानुसार है:Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
Whywhywhy

4
@whywhywhy मुझे लगता है कि आपको उस रेगेक्स में एक अतिरिक्त ओपनिंग ब्रैकेट मिला है। "(^ (PRN | AUX | NUL | CON | कॉम [1-9] | एलपीटी [1-9] | (\\ +) $) (\\ .. *) $।?) | (([\\ x00 - \\ X1f \\\\? *: \ "; \ _? / <>]) +] ([[\\।] +)" मेरे लिए काम किया।
विल्की

4
मैंने इस उत्तर में वर्णित उसी लेख को पढ़ा और प्रयोग के माध्यम से पाया कि COM0 और LPT0 को भी अनुमति नहीं है। @ इसे फिल्म्स के साथ काम करता है जो 'से शुरू होता है।':^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
mjohnsonengr

67

के लिए नेट फ्रेमवर्क पहले 3.5 यह काम करना चाहिए:

रेगुलर एक्सप्रेशन मैचिंग आपको कुछ हद तक मिलनी चाहिए। यहां System.IO.Path.InvalidPathCharsनिरंतर का उपयोग करके एक स्निपेट है;

bool IsValidFilename(string testName)
{
    Regex containsABadCharacter = new Regex("[" 
          + Regex.Escape(System.IO.Path.InvalidPathChars) + "]");
    if (containsABadCharacter.IsMatch(testName)) { return false; };

    // other checks for UNC, drive-path format, etc

    return true;
}

3.0 के बाद .Net फ्रेमवर्क के लिए यह काम करना चाहिए:

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx

रेगुलर एक्सप्रेशन मैचिंग आपको कुछ हद तक मिलनी चाहिए। यहां System.IO.Path.GetInvalidPathChars()निरंतर का उपयोग करके एक स्निपेट है;

bool IsValidFilename(string testName)
{
    Regex containsABadCharacter = new Regex("["
          + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]");
    if (containsABadCharacter.IsMatch(testName)) { return false; };

    // other checks for UNC, drive-path format, etc

    return true;
}

एक बार जब आप यह जान लेते हैं कि, आपको विभिन्न प्रारूपों, उदा c:\my\driveऔर के लिए भी जाँच करनी चाहिए\\server\share\dir\file.ext


यह केवल पथ का परीक्षण नहीं करता है, फ़ाइल नाम का नहीं?
यूजीन काटज़

30
string strTheseAreInvalidFileNameChars = नया स्ट्रिंग (System.IO.Path.GetInvalidFileNameChars ()); Regex regFixFileName = नया Regex ("[" + Regex.Escape (strTheseAreInvalidFileNameChars) + "]");
राओ

2
लोगों के थोड़े से शोध चमत्कार का काम करेंगे। मैंने परिवर्तनों को दर्शाने के लिए पोस्ट अपडेट की है।
एरिक फिलिप्स

1
कोड का दूसरा टुकड़ा संकलन नहीं करता है। "चार से [] कनवर्ट नहीं कर सकता स्ट्रिंग के लिए
पॉल हंट

1
@AshkanMobayenKhiabani: InvalidPathChars अप्रचलित है, लेकिन GetInvalidPathChars नहीं करता है।
इवानH

25

इसका उपयोग करने का प्रयास करें, और त्रुटि के लिए जाल। अनुमत सेट फ़ाइल सिस्टम या विंडोज के विभिन्न संस्करणों में बदल सकता है। दूसरे शब्दों में, यदि आप जानते हैं कि क्या विंडोज को नाम पसंद है, तो इसे नाम दें और इसे आपको बताएं।


1
यह एकमात्र ऐसा प्रतीत होता है जो सभी बाधाओं के खिलाफ परीक्षण करता है। इस पर अन्य उत्तरों को क्यों चुना जा रहा है?
अंतराल

5
@ गैप क्योंकि यह हमेशा काम नहीं करता है। उदाहरण के लिए, CON का उपयोग करने का प्रयास अक्सर सफल होगा, भले ही यह वास्तविक फ़ाइल न हो।
एंटीमनी

4
यह हमेशा एक अपवाद फेंकने की मेमोरी ओवरहेड से बचने के लिए बेहतर है, जहां संभव हो, हालांकि।
ओवेन ब्लैकर

2
इसके अलावा, आपके पास इसे एक्सेस करने की अनुमति नहीं हो सकती है; उदाहरण के लिए इसे लिखकर परीक्षण करें, भले ही आप इसे पढ़ सकते हैं या नहीं।
कोडलेकर

23

यह वर्ग फ़ाइल नाम और रास्तों को साफ करता है; इसका उपयोग करें

var myCleanPath = PathSanitizer.SanitizeFilename(myBadPath, ' ');

यहाँ कोड है;

/// <summary>
/// Cleans paths of invalid characters.
/// </summary>
public static class PathSanitizer
{
    /// <summary>
    /// The set of invalid filename characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidFilenameChars;
    /// <summary>
    /// The set of invalid path characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidPathChars;

    static PathSanitizer()
    {
        // set up the two arrays -- sorted once for speed.
        invalidFilenameChars = System.IO.Path.GetInvalidFileNameChars();
        invalidPathChars = System.IO.Path.GetInvalidPathChars();
        Array.Sort(invalidFilenameChars);
        Array.Sort(invalidPathChars);

    }

    /// <summary>
    /// Cleans a filename of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizeFilename(string input, char errorChar)
    {
        return Sanitize(input, invalidFilenameChars, errorChar);
    }

    /// <summary>
    /// Cleans a path of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizePath(string input, char errorChar)
    {
        return Sanitize(input, invalidPathChars, errorChar);
    }

    /// <summary>
    /// Cleans a string of invalid characters.
    /// </summary>
    /// <param name="input"></param>
    /// <param name="invalidChars"></param>
    /// <param name="errorChar"></param>
    /// <returns></returns>
    private static string Sanitize(string input, char[] invalidChars, char errorChar)
    {
        // null always sanitizes to null
        if (input == null) { return null; }
        StringBuilder result = new StringBuilder();
        foreach (var characterToTest in input)
        {
            // we binary search for the character in the invalid set. This should be lightning fast.
            if (Array.BinarySearch(invalidChars, characterToTest) >= 0)
            {
                // we found the character in the array of 
                result.Append(errorChar);
            }
            else
            {
                // the character was not found in invalid, so it is valid.
                result.Append(characterToTest);
            }
        }

        // we're done.
        return result.ToString();
    }

}

1
आपका जवाब यहां बेहतर हो सकता है: stackoverflow.com/questions/146134/…
nawfal

22

यही है वह जो मेरे द्वारा उपयोग किया जाता है:

    public static bool IsValidFileName(this string expression, bool platformIndependent)
    {
        string sPattern = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$";
        if (platformIndependent)
        {
           sPattern = @"^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?))\\)*[^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?$";
        }
        return (Regex.IsMatch(expression, sPattern, RegexOptions.CultureInvariant));
    }

पहला पैटर्न केवल Windows प्लेटफ़ॉर्म के लिए अमान्य / अवैध फ़ाइल नाम और वर्णों के साथ एक नियमित अभिव्यक्ति बनाता है। दूसरा एक ही करता है लेकिन यह सुनिश्चित करता है कि नाम किसी भी प्लेटफ़ॉर्म के लिए कानूनी है।


4
sPattern regex पीरियड कैरेक्टर के साथ फाइल शुरू करने की अनुमति नहीं देता है। लेकिन MSDN का कहना है कि "किसी नाम के पहले वर्ण के रूप में एक अवधि निर्दिष्ट करना स्वीकार्य है। उदाहरण के लिए," .temp "। मैं "। * *" को निकाल
दूंगा।

(मैंने अपने द्वारा छोड़ी गई बेहतर और हटाई गई प्रचलित टिप्पणियों को छोड़ दिया है) यह एक उत्तर के रेगेक्स से बेहतर है कि यह ".itignoreore", "..asdf" की अनुमति देता है, '<' और '>' या येन की अनुमति नहीं देता है। हस्ताक्षर, और अंत में स्थान या अवधि की अनुमति नहीं देता है (जो केवल डॉट्स से युक्त नामों को अस्वीकार करता है):@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
mjohnsonengr

मैंने परीक्षण की सभी फ़ाइलों के लिए यह विफल रहता है। इसे C: \ Windows \ System32 \ msxml6.dll के लिए चलाने से झूठी रिपोर्ट आती है।
Magicandre1981

@ Magicandre1981 आपको इसे केवल फ़ाइल नाम देने की आवश्यकता है, न कि पूरी तरह से योग्य पथ।
स्कॉट डोरमैन

ठीक है, लेकिन मुझे यह जांचने की आवश्यकता है कि क्या पूर्ण पथ वैध है। मैंने अब एक अलग समाधान का उपयोग किया।
Magicandre1981

18

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

"file.txt"
" file.txt"
"  file.txt"

इसमें से एक टेकअवे: कोड लिखते समय सावधानी बरतें जो ट्राइसेप्स को एक फाइल स्ट्रिंग से अग्रणी / पीछे ले जाता है।


10

यूजीन काट्ज के उत्तर को सरल बनाना:

bool IsFileNameCorrect(string fileName){
    return !fileName.Any(f=>Path.GetInvalidFileNameChars().Contains(f))
}

या

bool IsFileNameCorrect(string fileName){
    return fileName.All(f=>!Path.GetInvalidFileNameChars().Contains(f))
}

क्या आपका मतलब था: "वापसी! फ़ाइलनाम। कोई भी (f => पाथ.गेटइन्लाइडफाइलनामकैंस ()। इसमें शामिल हैं (च));" ?
जैक ग्रिफिन

@JackGriffin बेशक! आपके ध्यान के लिए धन्यवाद।
टीएमटी

जबकि यह कोड पढ़ने में बहुत अच्छा है, हमें इस बात का ध्यान रखना चाहिए कि क्षमा करें Path.GetInvalidFileNameChars। यहाँ एक नज़र डालें: Referenceource.microsoft.com/#mscorlib/system/io/path.cs,289 - आपके प्रत्येक चरित्र के लिए fileName, सरणी का एक क्लोन बनाया जाता है।
पियोट्र ज़िएरहोफर

"डीडी: \\\\\ एएए ..... AAAA"। मान्य नहीं है, लेकिन आपके कोड के लिए, यह है।
सिसियो पोस्तिकाओ

8

Microsoft Windows: Windows कर्नेल 1-31 (यानी, 0x01-0x1F) और वर्ण "*: <>? \ _" में वर्णों के उपयोग की मनाही करता है। हालाँकि NTFS प्रत्येक पथ घटक (निर्देशिका या फ़ाइल नाम) को 255 वर्ष लंबा होने की अनुमति देता है। लगभग 32767 वर्णों तक लंबा पथ, Windows कर्नेल केवल 259 वर्णों तक के पथों का समर्थन करता है। इसके अतिरिक्त, Windows MS-DOS डिवाइस के नाम AUX, CLOCK $, COM1, COM2, COM2, COM3, COM4, ​​COM5, COM6, COM6 को वर्जित करता है। COM7, COM8, COM9, CON9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL और PRN, साथ ही साथ ये नाम किसी भी एक्सटेंशन के साथ हैं (उदाहरण के लिए, AUX.txt), सिवाय इसके कि जब उपयोग किया जाए। लंबे UNC पथ (उदा। \। \ C: \ nul.txt या \? \ D: \ aux \ con)। (वास्तव में, CLOCK $ का उपयोग यदि कोई एक्सटेंशन प्रदान किया जाता है।) ये प्रतिबंध केवल Windows पर लागू होते हैं - लिनक्स, उदाहरण के लिए, "*: <> का उपयोग करने की अनुमति देता है? \ _ | यहां तक ​​कि NTFS में भी।

स्रोत: http://en.wikipedia.org/wiki/Filename


1
मैं "CLOCK $" नाम की एक फ़ाइल बना सकता हूं। विंडोज 7.
rory.ap

7

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


6

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

इस तरह से आप न केवल यह जानते हैं कि पथ में केवल मान्य विंडो वर्ण हैं, लेकिन यदि यह वास्तव में एक पथ का प्रतिनिधित्व करता है जिसे इस प्रक्रिया द्वारा लिखा जा सकता है।


6

मैं इसका उपयोग अपवादों को फेंकने के बिना फ़ाइल नाम में अमान्य वर्णों से छुटकारा पाने के लिए करता हूं:

private static readonly Regex InvalidFileRegex = new Regex(
    string.Format("[{0}]", Regex.Escape(@"<>:""/\|?*")));

public static string SanitizeFileName(string fileName)
{
    return InvalidFileRegex.Replace(fileName, string.Empty);
}

5

इसके अलावा CON, PRN, AUX, NUL, COM # और कुछ अन्य कभी भी किसी भी एक्सटेंशन के साथ किसी भी निर्देशिका में कानूनी फ़ाइल नाम नहीं हैं।


1
यह सच्चाई का केवल आधा हिस्सा है। यदि आप CreateFile के यूनिकोड संस्करण को कॉल कर रहे हैं, तो इन नामों के साथ फाइल बना सकते हैं ("\\! \" के साथ फ़ाइल नाम को उपसर्ग कर रहे हैं) "।
वर्नर हेन्ज

यह कथन अधूरा है और LPT #
थॉमस वेलर

4

अन्य उत्तरों के पूरक के लिए, यहां कुछ अतिरिक्त किनारे मामले हैं, जिन पर आप विचार करना चाहते हैं।

  • यदि आप किसी फ़ाइल में किसी कार्यपुस्तिका को सहेजते हैं, तो Excel में समस्याएँ हो सकती हैं, जिनके नाम में '[' या '' अक्षर हैं। देखें http://support.microsoft.com/kb/215205 जानकारी के लिए।

  • शेयरपॉइंट पर प्रतिबंधों का एक पूरा अतिरिक्त सेट है। देखें http://support.microsoft.com/kb/905231 जानकारी के लिए।


3

से MSDN , यहाँ वर्णों की एक सूची है कि अनुमति नहीं है बताया गया है:

नाम के लिए वर्तमान कोड पृष्ठ में लगभग किसी भी वर्ण का उपयोग करें, जिसमें यूनिकोड वर्ण और विस्तारित वर्ण सेट में वर्ण (128-255) शामिल हैं, निम्न को छोड़कर:

  • निम्नलिखित आरक्षित वर्णों की अनुमति नहीं है: <>: "/ \ |?"
  • जिन वर्णों का पूर्णांक निरूपण 31 से शून्य से सीमा में है उन्हें अनुमति नहीं है।
  • कोई अन्य वर्ण जो लक्ष्य फ़ाइल सिस्टम को अनुमति नहीं देता है।

2

इसके अलावा गंतव्य फ़ाइल प्रणाली महत्वपूर्ण है।

NTFS के तहत, कुछ फाइलें विशिष्ट निर्देशिकाओं में नहीं बनाई जा सकती हैं। ईजी $ बूट रूट में


2
निश्चित रूप से यह एक NTFS नामकरण नियम के कारण नहीं है, लेकिन केवल इसलिए कि एक फ़ाइल जिसे $Bootपहले से ही निर्देशिका में मौजूद है?
ईसाई हैटर

2

यह पहले से ही उत्तर दिया गया प्रश्न है, लेकिन केवल "अन्य विकल्प" के लिए, यहां एक गैर-आदर्श है:

(गैर-आदर्श क्योंकि प्रवाह नियंत्रण के रूप में अपवाद का उपयोग करना "बैड थिंग" है, आमतौर पर)

public static bool IsLegalFilename(string name)
{
    try 
    {
        var fileInfo = new FileInfo(name);
        return true;
    }
    catch
    {
        return false;
    }
}

आपके उदाहरण ने CON फ़ाइल (C: \ temp \ CON) के लिए काम नहीं किया।
tcbrazil

लेकिन 'C: \ temp \ CON' एक वैध फ़ाइल नाम नहीं है? ऐसा क्यों नहीं होगा?
मार्क ए। डोनोहे

@MarqueIV - नहीं, यह मान्य नहीं है। ऊपर दिए गए सभी उत्तरों और टिप्पणियों को पढ़ें, या इसे स्वयं आज़माएं और देखें।
rory.ap

@ जेर, "/ उदाहरण" कानूनी नहीं है, फिर भी आपकी विधि वापस आती है true
rory.ap

आआआह… मुझे ah CON ’वाला हिस्सा याद आ गया। नाम स्वयं एक स्ट्रिंग दृष्टिकोण से मान्य है (जिसे मैं संदर्भित कर रहा था), लेकिन मैं देखता हूं कि CON अब एक आरक्षित नाम है, जो इसे Windows दृष्टिकोण से गैर-मान्य बनाता है। मेरी गलती।
मार्क ए। डोनोहे

2

इस स्थिति के लिए नियमित अभिव्यक्तियाँ ओवरकिल हैं। आप के String.IndexOfAny()साथ संयोजन में विधि का उपयोग कर सकते हैं Path.GetInvalidPathChars()और Path.GetInvalidFileNameChars()

यह भी ध्यान दें कि दोनों Path.GetInvalidXXX()विधियाँ एक आंतरिक सरणी को क्लोन करती हैं और क्लोन को वापस करती हैं। इसलिए यदि आप इसे बहुत (हजारों और हजारों बार) करने जा रहे हैं, तो आप पुन: उपयोग के लिए अमान्य वर्ण सरणी की एक प्रतिलिपि कैश कर सकते हैं।


2

यदि आप केवल यह जाँचने का प्रयास कर रहे हैं कि आपके फ़ाइल नाम / पथ को रखने वाले स्ट्रिंग में कोई अमान्य वर्ण है या नहीं, तो मैंने पाया कि सबसे तेज़ विधि Split()फ़ाइल नाम को भागों के एक सरणी में विभाजित करने के लिए उपयोग करना है जहाँ कोई अमान्य वर्ण है। यदि परिणाम केवल 1 का एक सरणी है, तो कोई अमान्य वर्ण नहीं हैं। :-)

var nameToTest = "Best file name \"ever\".txt";
bool isInvalidName = nameToTest.Split(System.IO.Path.GetInvalidFileNameChars()).Length > 1;

var pathToTest = "C:\\My Folder <secrets>\\";
bool isInvalidPath = pathToTest.Split(System.IO.Path.GetInvalidPathChars()).Length > 1;

मैंने LinqPad में 1,000,000 बार फ़ाइल / पथ नाम पर ऊपर उल्लिखित इस और अन्य तरीकों को चलाने की कोशिश की।

उपयोग Split()केवल ~ 850ms है।

उपयोग करना Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")लगभग 6 सेकंड है।

अधिक जटिल नियमित अभिव्यक्तियाँ निष्पक्ष रूप से बदतर होती हैं, जैसा कि अन्य विकल्पों में से कुछ करते हैं, जैसे कि Pathफ़ाइल का नाम पाने के लिए कक्षा में विभिन्न तरीकों का उपयोग करना और उनकी आंतरिक मान्यता को काम करने देना (ज्यादातर अपवाद हैंडलिंग के ओवरहेड के कारण होने की संभावना है)।

दी गई यह बहुत बार आपको 1 मिलियन फ़ाइल नामों को मान्य करने की आवश्यकता नहीं है, इसलिए इन तरीकों में से अधिकांश के लिए एक एकल पुनरावृत्ति ठीक है। यदि आप केवल अमान्य वर्णों की तलाश कर रहे हैं, लेकिन यह अभी भी बहुत कुशल और प्रभावी है।


1

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

यह एक मान्य विशेषता है जिसे मैंने एक वैध फ़ाइल नाम के लिए जांचने के लिए बनाया है।

public class ValidFileNameAttribute : ValidationAttribute
{
    public ValidFileNameAttribute()
    {
        RequireExtension = true;
        ErrorMessage = "{0} is an Invalid Filename";
        MaxLength = 255; //superseeded in modern windows environments
    }
    public override bool IsValid(object value)
    {
        //http://stackoverflow.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists
        var fileName = (string)value;
        if (string.IsNullOrEmpty(fileName)) { return true;  }
        if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 ||
            (!AllowHidden && fileName[0] == '.') ||
            fileName[fileName.Length - 1]== '.' ||
            fileName.Length > MaxLength)
        {
            return false;
        }
        string extension = Path.GetExtension(fileName);
        return (!RequireExtension || extension != string.Empty)
            && (ExtensionList==null || ExtensionList.Contains(extension));
    }
    private const string _sepChar = ",";
    private IEnumerable<string> ExtensionList { get; set; }
    public bool AllowHidden { get; set; }
    public bool RequireExtension { get; set; }
    public int MaxLength { get; set; }
    public string AllowedExtensions {
        get { return string.Join(_sepChar, ExtensionList); } 
        set {
            if (string.IsNullOrEmpty(value))
            { ExtensionList = null; }
            else {
                ExtensionList = value.Split(new char[] { _sepChar[0] })
                    .Select(s => s[0] == '.' ? s : ('.' + s))
                    .ToList();
            }
    } }

    public override bool RequiresValidationContext => false;
}

और परीक्षण

[TestMethod]
public void TestFilenameAttribute()
{
    var rxa = new ValidFileNameAttribute();
    Assert.IsFalse(rxa.IsValid("pptx."));
    Assert.IsFalse(rxa.IsValid("pp.tx."));
    Assert.IsFalse(rxa.IsValid("."));
    Assert.IsFalse(rxa.IsValid(".pp.tx"));
    Assert.IsFalse(rxa.IsValid(".pptx"));
    Assert.IsFalse(rxa.IsValid("pptx"));
    Assert.IsFalse(rxa.IsValid("a/abc.pptx"));
    Assert.IsFalse(rxa.IsValid("a\\abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c:abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c<abc.pptx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
    rxa = new ValidFileNameAttribute { AllowedExtensions = ".pptx" };
    Assert.IsFalse(rxa.IsValid("abc.docx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
}

1

मेरा प्रयास:

using System.IO;

static class PathUtils
{
  public static string IsValidFullPath([NotNull] string fullPath)
  {
    if (string.IsNullOrWhiteSpace(fullPath))
      return "Path is null, empty or white space.";

    bool pathContainsInvalidChars = fullPath.IndexOfAny(Path.GetInvalidPathChars()) != -1;
    if (pathContainsInvalidChars)
      return "Path contains invalid characters.";

    string fileName = Path.GetFileName(fullPath);
    if (fileName == "")
      return "Path must contain a file name.";

    bool fileNameContainsInvalidChars = fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;
    if (fileNameContainsInvalidChars)
      return "File name contains invalid characters.";

    if (!Path.IsPathRooted(fullPath))
      return "The path must be absolute.";

    return "";
  }
}

यह सही नहीं है क्योंकि Path.GetInvalidPathCharsफ़ाइल और निर्देशिका नामों में अमान्य वर्णों का पूरा सेट वापस नहीं करता है और निश्चित रूप से बहुत अधिक सूक्ष्मताएं हैं।

इसलिए मैं पूरक के रूप में इस विधि का उपयोग करता हूं:

public static bool TestIfFileCanBeCreated([NotNull] string fullPath)
{
  if (string.IsNullOrWhiteSpace(fullPath))
    throw new ArgumentException("Value cannot be null or whitespace.", "fullPath");

  string directoryName = Path.GetDirectoryName(fullPath);
  if (directoryName != null) Directory.CreateDirectory(directoryName);
  try
  {
    using (new FileStream(fullPath, FileMode.CreateNew)) { }
    File.Delete(fullPath);
    return true;
  }
  catch (IOException)
  {
    return false;
  }
}

यह फ़ाइल बनाने की कोशिश करता है और अपवाद होने पर झूठी वापसी करता है। बेशक, मुझे फ़ाइल बनाने की आवश्यकता है लेकिन मुझे लगता है कि यह ऐसा करने का सबसे सुरक्षित तरीका है। कृपया यह भी ध्यान दें कि मैं उन निर्देशिकाओं को नहीं हटा रहा हूँ जिन्हें बनाया गया है।

आप मूल सत्यापन करने के लिए पहली विधि का भी उपयोग कर सकते हैं, और फिर पथ का उपयोग करने पर अपवादों को सावधानीपूर्वक संभाल सकते हैं।


0

मेरा सुझाव है कि केवल पाथ का उपयोग करें। GetFullPath ()

string tagetFileFullNameToBeChecked;
try
{
  Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
  // invalid chars found
}

जवाब के साथ कुछ स्पष्टीकरण जोड़ें कि यह उत्तर ओपी को वर्तमान मुद्दे को ठीक करने में कैसे मदद करता है
ρяєρ withя K

AugumentExcpetion के लिए MSDN में दस्तावेज़ देखें, यह पढ़ता है: पथ एक शून्य-लंबाई वाला स्ट्रिंग है, जिसमें केवल सफेद स्थान है, या इसमें GetInvalidPathChars में परिभाषित एक या अधिक अमान्य वर्ण हैं। -या- सिस्टम निरपेक्ष पथ प्राप्त नहीं कर सका।
टोनी सन

सिद्धांत रूप में (डॉक्स के अनुसार) यह काम करना चाहिए, हालांकि समस्या कम से कम .NET कोर 3.1 में है, यह नहीं है।
मिशेल जानसन

0

मुझे यह विचार किसी से मिला। - कौन नहीं जानता। OS को भारी उठाने दें।

public bool IsPathFileNameGood(string fname)
{
    bool rc = Constants.Fail;
    try
    {
        this._stream = new StreamWriter(fname, true);
        rc = Constants.Pass;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Problem opening file");
        rc = Constants.Fail;
    }
    return rc;
}

0

यह जाँच

static bool IsValidFileName(string name)
{
    return
        !string.IsNullOrWhiteSpace(name) &&
        name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
        !Path.GetFullPath(name).StartsWith(@"\\.\");
}

बाहर अमान्य वर्ण (साथ नाम फिल्टर <>:"/\|?*और ASCII 0-31), साथ ही सुरक्षित डॉस उपकरणों ( CON, NUL, COMx)। यह प्रमुख रिक्त स्थान और सभी-डॉट-नामों की अनुमति देता है, जिसके अनुरूप Path.GetFullPath। (अग्रणी स्थानों के साथ फ़ाइल बनाना मेरे सिस्टम पर सफल होता है)।


उपयोग किया गया .NET फ्रेमवर्क 4.7.1, विंडोज 7 पर परीक्षण किया गया।


0

स्ट्रिंग में इल्लीगल वर्णों के सत्यापन के लिए एक लाइनर:

public static bool IsValidFilename(string testName) => !Regex.IsMatch(testName, "[" + Regex.Escape(new string(System.IO.Path.InvalidPathChars)) + "]");

0

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


-1

विंडोज फ़ाइलनाम बहुत अप्रतिबंधित हैं, इसलिए वास्तव में यह भी इतना मुद्दा नहीं हो सकता है । Windows द्वारा रोक दिए गए वर्ण हैं:

\ / : * ? " < > |

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


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