How do I check if a given string is a legal/valid file name under Windows?

后端 未结 27 1379
-上瘾入骨i
-上瘾入骨i 2020-11-22 09:38

I want to include a batch file rename functionality in my application. A user can type a destination filename pattern and (after replacing some wildcards in the pattern) I n

相关标签:
27条回答
  • 2020-11-22 10:30

    This class cleans filenames and paths; use it like

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

    Here's the code;

    /// <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();
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 10:30

    From MSDN, here's a list of characters that aren't allowed:

    Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:

    • The following reserved characters are not allowed: < > : " / \ | ? *
    • Characters whose integer representations are in the range from zero through 31 are not allowed.
    • Any other character that the target file system does not allow.
    0 讨论(0)
  • 2020-11-22 10:30

    In my opinion, the only proper answer to this question is to try to use the path and let the OS and filesystem validate it. Otherwise you are just reimplementing (and probably poorly) all the validation rules that the OS and filesystem already use and if those rules are changed in the future you will have to change your code to match them.

    0 讨论(0)
  • 2020-11-22 10:33

    Microsoft Windows: Windows kernel forbids the use of characters in range 1-31 (i.e., 0x01-0x1F) and characters " * : < > ? \ |. Although NTFS allows each path component (directory or filename) to be 255 characters long and paths up to about 32767 characters long, the Windows kernel only supports paths up to 259 characters long. Additionally, Windows forbids the use of the MS-DOS device names AUX, CLOCK$, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL and PRN, as well as these names with any extension (for example, AUX.txt), except when using Long UNC paths (ex. \.\C:\nul.txt or \?\D:\aux\con). (In fact, CLOCK$ may be used if an extension is provided.) These restrictions only apply to Windows - Linux, for example, allows use of " * : < > ? \ | even in NTFS.

    Source: http://en.wikipedia.org/wiki/Filename

    0 讨论(0)
  • 2020-11-22 10:33

    Rather than explicitly include all possible characters, you could do a regex to check for the presence of illegal characters, and report an error then. Ideally your application should name the files exactly as the user wishes, and only cry foul if it stumbles across an error.

    0 讨论(0)
  • 2020-11-22 10:34

    This check

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

    filters out names with invalid chars (<>:"/\|?* and ASCII 0-31), as well as reserved DOS devices (CON, NUL, COMx). It allows leading spaces and all-dot-names, consistent with Path.GetFullPath. (Creating file with leading spaces succeeds on my system).


    Used .NET Framework 4.7.1, tested on Windows 7.

    0 讨论(0)
提交回复
热议问题