【问题标题】:How do I check if a given string is a legal/valid file name under Windows?如何检查给定的字符串是否是 Windows 下的合法/有效文件名?
【发布时间】:2010-09-08 22:22:20
【问题描述】:

我想在我的应用程序中包含批处理文件重命名功能。用户可以键入目标文件名模式,并且(在替换模式中的一些通配符之后)我需要检查它是否会成为 Windows 下的合法文件名。我尝试使用像[a-zA-Z0-9_]+ 这样的正则表达式,但它不包括来自各种语言的许多特定于国家的字符(例如变音符号等)。进行此类检查的最佳方法是什么?

【问题讨论】:

  • 如果您要使用正则表达式的任何答案,我建议使用静态编译的正则表达式..

标签: c# windows file filesystems


【解决方案1】:

您可以使用正则表达式检查是否存在非法字符,然后报告错误,而不是显式包含所有可能的字符。理想情况下,您的应用程序应该完全按照用户的意愿命名文件,并且只有在偶然发现错误时才会大声疾呼。

【讨论】:

    【解决方案2】:

    来自MSDN,这里是不允许使用的字符列表:

    几乎可以使用当前代码页中的任何字符作为名称,包括 Unicode 字符和扩展字符集 (128–255) 中的字符,但以下字符除外:

    • 不允许使用以下保留字符: : " / \ | ? *
    • 不允许使用整数表示在 0 到 31 范围内的字符。
    • 目标文件系统不允许的任何其他字符。

    【讨论】:

      【解决方案3】:

      您可以从Path.GetInvalidPathCharsGetInvalidFileNameChars 获取无效字符列表。

      UPD:请参阅Steve Cooper's suggestion,了解如何在正则表达式中使用它们。

      UPD2:请注意,根据 MSDN 中的备注部分“不能保证从此方法返回的数组包含文件和目录名称中无效的完整字符集。” The answer provided by sixlettervaliables 详细介绍。

      【讨论】:

      • 这没有回答问题;有许多仅由有效字符组成的字符串(例如“....”、“CON”、数百个字符长的字符串)不是有效的文件名。
      • 还有其他人对 MS 没有为此功能提供系统级功能/API 而不是每个开发人员必须自己解决方案感到失望吗?想知道这是否有很好的理由,或者只是 MS 部分的疏忽。
      • @High Arch:请参阅问题“在 C# 中检查文件名是否可能有效(不存在)”的答案。 (虽然一些聪明的人结束了这个问题,支持这个问题......)
      【解决方案4】:

      Windows 文件名非常不受限制,因此实际上它甚至可能 不是什么大问题。 Windows 不允许的字符有:

      \ / : * ? " < > |
      

      您可以轻松编写一个表达式来检查这些字符是否存在。更好的解决方案是尝试按照用户的需要命名文件,并在文件名不正确时提醒他们。

      【讨论】:

      • 字符
      【解决方案5】:

      此外,CON、PRN、AUX、NUL、COM# 和其他一些在任何具有任何扩展名的目录中都不是合法的文件名。

      【讨论】:

      • 这只是事实的一半。如果调用 CreateFile 的 unicode 版本(文件名前缀为“\\?\”),您可以使用这些名称创建文件。
      • 此语句不完整,遗漏了 LPT#
      【解决方案6】:

      Microsoft Windows:Windows 内核禁止使用 1-31 范围内的字符(即 0x01-0x1F)和字符“ * : ? \ |。虽然 NTFS 允许每个路径组件(目录或文件名)为 255字符长和路径最多约 32767 个字符,Windows 内核仅支持最多 259 个字符长的路径。此外,Windows 禁止使用 MS-DOS 设备名称 AUX、CLOCK$、COM1、COM2、COM3、COM4、COM5 , COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL 和 PRN,以及这些带有任何扩展名的名称(例如,AUX.txt),除非使用长 UNC 路径(例如 \.\C:\nul.txt 或 \?\D:\aux\con)。(事实上,如果提供了扩展名,则可以使用 CLOCK$。)这些限制仅适用到 Windows - Linux,例如,允许使用 " * : ? \ |即使在 NTFS 中。

      来源:http://en.wikipedia.org/wiki/Filename

      【讨论】:

      • 我可以创建一个名为“CLOCK$”的文件就好了。视窗 7。
      【解决方案7】:

      对于 3.5 之前的 .Net 框架,这应该可以工作:

      正则表达式匹配应该可以帮助您。这是一个使用 System.IO.Path.InvalidPathChars 常量的 sn-p;

      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 Frameworks,这应该可以工作:

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

      正则表达式匹配应该可以帮助您。这是一个使用 System.IO.Path.GetInvalidPathChars() 常量的 sn-p;

      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

      【讨论】:

      • string strTheseAreInvalidFileNameChars = new string(System.IO.Path.GetInvalidFileNameChars()) ;正则表达式 regFixFileName = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars ) + "]");
      • 人们的一点研究会产生奇迹。我已更新帖子以反映更改。
      • 第二段代码无法编译。 "无法从 char[] 转换为字符串
      • +1 表示代码,但请将 Path.GetInvalidPathChars() 替换为 Path.GetInvalidFileNameChars(),因为 Path.GetInvalidPathChars() 现在已过时
      • @AshkanMobayenKhiabani:InvalidPathChars 已过时,但 GetInvalidPathChars 没有。
      【解决方案8】:

      问题是您是否试图确定路径名是否是合法的 Windows 路径,或者它在运行代码的系统上是否合法?我觉得后者更重要,所以我个人可能会分解完整路径并尝试使用_mkdir创建文件所属的目录,然后尝试创建文件。

      这样你不仅知道路径是否只包含有效的windows字符,而且它是否真的代表了一个可以被这个进程写入的路径。

      【讨论】:

        【解决方案9】:

        来自MSDN's "Naming a File or Directory," 以下是 Windows 下合法文件名的一般约定:

        您可以使用当前代码页中的任何字符(Unicode/ANSI 127 以上),除了:

        • &lt;&gt;:"/\|?*
        • 整数表示为 0-31(小于 ASCII 空格)的字符
        • 目标文件系统不允许的任何其他字符(例如,尾随句点或空格)
        • 任何 DOS 名称:CON、PRN、AUX、NUL、COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6 , LPT7, LPT8, LPT9(并避免 AUX.txt 等)
        • 文件名全是句点

        一些可选的检查:

        • 文件路径(包括文件名)不得超过 260 个字符(不使用 \?\ 前缀)
        • 使用\?\时超过32,000个字符的Unicode文件路径(包括文件名)(注意前缀可能会扩展目录组件并导致超出32,000个限制)

        【讨论】:

        • +1 用于包含保留的文件名 - 以前的答案中遗漏了这些文件名。
        • "AUX" 如果您使用 "\\?\" 语法,它是一个完全可用的文件名。当然,不使用该语法的程序在处理它时会遇到真正的问题......(在 XP 上测试)
        • 上述所有这些条件的正确正则表达式如下:Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/&lt;&gt;])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
        • @whywhywhy 我认为您在该正则表达式中有一个额外的左括号。 "(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\ x00-\\x1f\\\\?*:\";‌​|/])+)|([\\. ]+)" 为我工作。
        • 我阅读了这个答案中提到的同一篇文章,通过实验发现 COM0 和 LPT0 也是不允许的。 @dlf 这个适用于以'.'开头的文件名:^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/&lt;&gt;]+(?&lt;![\s.])$
        【解决方案10】:

        尝试使用它,并捕获错误。允许的集合可能会在文件系统或不同版本的 Windows 之间发生变化。换句话说,如果你想知道 Windows 是否喜欢这个名字,就把名字交给它,让它告诉你。

        【讨论】:

        • 这似乎是唯一一个针对所有约束进行测试的。为什么选择其他答案而不是这个?
        • @gap 因为它并不总是有效。例如,尝试访问 CON 通常会成功,即使它不是真实文件。
        • 在可能的情况下,最好避免抛出异常的内存开销。
        • 另外,您可能没有权限访问它;例如通过写作来测试它,即使你可以阅读它,如果它存在或将存在。
        【解决方案11】:

        这是我用的:

            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 平台的无效/非法文件名和字符。第二个做同样的事情,但确保该名称对于任何平台都是合法的。

        【讨论】:

        • sPattern 正则表达式不允许文件以句点字符开头。但是MSDN says“可以将句点指定为名称的第一个字符。例如,“.temp””。我会删除 "\..*" 以使 .gitignore 正确的文件名:)
        • (我已经逐渐改进并删除了我离开的 prev cmets)这个比答案的正则表达式更好,因为它允许“.gitignore”,“..asdf”,不允许'' 或日元符号,并且不允许结尾有空格或句点(不允许名称仅由点组成):@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/&lt;&gt;]+(?&lt;![\s.])$"
        • 我测试的所有文件都失败了。为 C:\Windows\System32\msxml6.dll 运行它报告错误。
        • @magicandre1981 你只需要给它文件名,而不是完全限定的路径。
        • 好的,但我需要检查完整路径是否有效。我现在使用了不同的解决方案。
        【解决方案12】:

        对于这种情况,正则表达式是多余的。您可以将String.IndexOfAny() 方法与Path.GetInvalidPathChars()Path.GetInvalidFileNameChars() 结合使用。

        另请注意,Path.GetInvalidXXX() 方法都克隆了一个内部数组并返回克隆。因此,如果您要经常这样做(成千上万次),您可以缓存无效字符数组的副本以供重复使用。

        【讨论】:

          【解决方案13】:

          要记住一个极端情况,当我第一次发现它时让我很惊讶:Windows 允许文件名中的前导空格字符!例如,以下是 Windows 上所有合法且不同的文件名(减去引号):

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

          从中得出一个结论:在编写从文件名字符串中修剪前导/尾随空格的代码时要小心。

          【讨论】:

            【解决方案14】:

            这个类清理文件名和路径;像使用它

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

            【讨论】:

            【解决方案15】:

            目标文件系统也很重要。

            在 NTFS 下,某些文件无法在特定目录中创建。 例如。 $在根目录下启动

            【讨论】:

            • 这肯定不是因为 NTFS 命名规则,而仅仅是因为目录中已经存在一个名为 $Boot 的文件?
            【解决方案16】:

            为了补充其他答案,您可能需要考虑以下几个额外的边缘情况。

            【讨论】:

              【解决方案17】:

              这是一个已经回答的问题,但只是为了“其他选项”,这是一个不理想的问题:

              (不理想,因为使用异常作为流程控制通常是“坏事”)

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

              【讨论】:

              • 您的示例不适用于 CON 文件 (C:\temp\CON)。
              • 但是 'C:\temp\CON' 不是一个有效的文件名吗?为什么不呢?
              • @MarqueIV -- 不,它无效。阅读上面所有的答案和cmets,或者自己试试看。
              • @Jer, "/example" 不合法,但您的方法返回 true
              • Aaaah...我错过了“CON”部分。从 string 的角度来看,该名称本身是有效的(这就是我所指的),但我现在看到 CON 是一个保留名称,因此从 Windows 的角度来看它是无效的。我的错。
              【解决方案18】:

              我用它来删除文件名中的无效字符而不抛出异常:

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

              【讨论】:

                【解决方案19】:

                我建议只使用 Path.GetFullPath()

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

                【讨论】:

                • 添加一些解释,说明此答案如何帮助 OP 解决当前问题
                • 有关 AugumentExcpetion,请参阅 MSDN 中的文档,它显示:路径是零长度字符串,仅包含空格,或包含 GetInvalidPathChars 中定义的一个或多个无效字符。 - 或 - 系统无法检索绝对路径。
                • 理论上(根据文档)这应该有效,但问题是至少在 .NET Core 3.1 中,它没有。
                【解决方案20】:

                简化 Eugene Katz 的答案:

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

                或者

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

                【讨论】:

                • 您的意思是:“return !fileName.Any(f=>Path.GetInvalidFileNameChars().Contains(f));” ?
                • @JackGriffin 当然!感谢您的关注。
                • 虽然这段代码读起来很舒服,但我们应该考虑到Path.GetInvalidFileNameChars 的内部问题。看看这里:referencesource.microsoft.com/#mscorlib/system/io/path.cs,289 - 对于fileName 的每个字符,都会创建一个数组的克隆。
                • "DD:\\\\\AAA.....AAAA"。无效,但对于您的代码,有效。
                【解决方案21】:

                如果文件名太长并且在 Windows 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"));
                }
                

                【讨论】:

                  【解决方案22】:

                  如果您只是想检查包含您的文件名/路径的字符串是否有任何无效字符,我发现的最快方法是使用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 类上的各种方法来获取文件名并让它们的内部验证完成工作(很可能是由于开销异常处理)。

                  当然,您并不经常需要验证 100 万个文件名,因此对于大多数这些方法来说,一次迭代就可以了。但是,如果您只查找无效字符,它仍然非常有效。

                  【讨论】:

                    【解决方案23】:

                    我的尝试:

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

                    它会尝试创建文件并在出现异常时返回 false。当然,我需要创建文件,但我认为这是最安全的方法。另请注意,我不会删除已创建的目录。

                    你也可以用第一种方法做基本的验证,然后在使用路径的时候小心处理异常。

                    【讨论】:

                      【解决方案24】:

                      我从某人那里得到了这个想法。 - 不知道是谁。让操作系统完成繁重的工作。

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

                      【讨论】:

                      • 这应该是公认的答案(网络路径可能除外)。
                      【解决方案25】:

                      这张支票

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

                      过滤掉带有无效字符的名称(&lt;&gt;:"/\|?* 和 ASCII 0-31),以及保留的 DOS 设备(CONNULCOMx)。它允许前导空格和全点名称,与Path.GetFullPath 一致。 (在我的系统上成功创建带有前导空格的文件)。


                      使用 .NET Framework 4.7.1,在 Windows 7 上测试。

                      【讨论】:

                        【解决方案26】:

                        一个用于验证字符串中非法字符的衬垫:

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

                        【讨论】:

                          【解决方案27】:

                          在我看来,这个问题的唯一正确答案是尝试使用路径并让操作系统和文件系统验证它。否则,您只是重新实现(并且可能很糟糕)操作系统和文件系统已经使用的所有验证规则,如果将来更改这些规则,您将不得不更改代码以匹配它们。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2018-03-21
                            • 2012-04-27
                            • 2022-12-15
                            • 1970-01-01
                            • 1970-01-01
                            • 2011-07-03
                            • 2020-10-15
                            相关资源
                            最近更新 更多