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

后端 未结 27 1351
-上瘾入骨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:36

    My attempt:

    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 "";
      }
    }
    

    This is not perfect because Path.GetInvalidPathChars does not return the complete set of characters that are invalid in file and directory names and of course there's plenty more subtleties.

    So I use this method as a complement:

    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;
      }
    }
    

    It tries to create the file and return false if there is an exception. Of course, I need to create the file but I think it's the safest way to do that. Please also note that I am not deleting directories that have been created.

    You can also use the first method to do basic validation, and then handle carefully the exceptions when the path is used.

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

    You can get a list of invalid characters from Path.GetInvalidPathChars and GetInvalidFileNameChars.

    UPD: See Steve Cooper's suggestion on how to use these in a regular expression.

    UPD2: Note that according to the Remarks section in MSDN "The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names." The answer provided by sixlettervaliables goes into more details.

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

    From MSDN's "Naming a File or Directory," here are the general conventions for what a legal file name is under Windows:

    You may use any character in the current code page (Unicode/ANSI above 127), except:

    • < > : " / \ | ? *
    • Characters whose integer representations are 0-31 (less than ASCII space)
    • Any other character that the target file system does not allow (say, trailing periods or spaces)
    • Any of the DOS names: CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 (and avoid AUX.txt, etc)
    • The file name is all periods

    Some optional things to check:

    • File paths (including the file name) may not have more than 260 characters (that don't use the \?\ prefix)
    • Unicode file paths (including the file name) with more than 32,000 characters when using \?\ (note that prefix may expand directory components and cause it to overflow the 32,000 limit)
    0 讨论(0)
提交回复
热议问题