【问题标题】:In C# check that filename is *possibly* valid (not that it exists) [duplicate]在 C# 中检查文件名是否*可能*有效(不存在)[重复]
【发布时间】:2010-09-30 03:24:27
【问题描述】:

System.IO 命名空间中是否有检查文件名有效性的方法?

例如,C:\foo\bar 会验证,:"~-* 不会

或者有点棘手,X:\foo\bar 会验证系统上是否有 X: 驱动器,否则不会。

我想我自己可以写这样一个方法,但我对内置的更感兴趣。

【问题讨论】:

  • “不是它退出”是否需要验证文件夹是否存在?支票的界限是什么?驱动器存在且字符都有效?

标签: c# validation file


【解决方案1】:

您可以从Path.GetInvalidPathCharsGetInvalidFileNameChars 中获取无效字符列表,如this question 中所述。

正如 jberger 所指出的,还有一些其他字符未包含在此方法的响应中。有关 windows 平台的更多详细信息,请查看 MSDN 上的Naming Files, Paths and Namespaces

作为 Micah points out,有 Directory.GetLogicalDrives 获取有效驱动器列表。

【讨论】:

  • "此方法返回的数组不保证包含文件和目录名称中无效的 完整 字符集。" Remarks
  • 让我重申一下。仅字符不足以知道它是有效的。例如,: 有效零次或一次,但它并不总是字符串中的第二个字符(如果存在)!
  • 这是不正确的。某些名称也被禁止,而不仅仅是某些字符。
  • "DD:\\\\\AAA.....AAAA"。无效,但对于您的代码,有效。
【解决方案2】:

我想我会发布一个解决方案,我是在寻找相同问题的可靠解决方案后从我找到的一些答案中拼凑而成的。希望它可以帮助其他人。

using System;
using System.IO;
//..

public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
    if (string.IsNullOrEmpty(path)) { return false; }
    string root = null;
    string directory = null;
    string filename = null;
    try
    {
        // throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
        root = Path.GetPathRoot(path);

        // throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
        // -or- String.Empty was passed to path.
        directory = Path.GetDirectoryName(path);

        // path contains one or more of the invalid characters defined in GetInvalidPathChars
        if (IncludeFileName) { filename = Path.GetFileName(path); }
    }
    catch (ArgumentException)
    {
        return false;
    }

    // null if path is null, or an empty string if path does not contain root directory information
    if (String.IsNullOrEmpty(root)) { return false; }

    // null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
    if (String.IsNullOrEmpty(directory)) { return false; }

    if (RequireFileName)
    {
        // if the last character of path is a directory or volume separator character, this method returns String.Empty
        if (String.IsNullOrEmpty(filename)) { return false; }

        // check for illegal chars in filename
        if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
    }
    return true;
}

【讨论】:

    【解决方案3】:

    试试这个方法,它会尝试覆盖所有可能的异常情况。它适用于几乎所有与 Windows 相关的路径。

    /// <summary>
    /// Validate the Path. If path is relative append the path to the project directory by default.
    /// </summary>
    /// <param name="path">Path to validate</param>
    /// <param name="RelativePath">Relative path</param>
    /// <param name="Extension">If want to check for File Path</param>
    /// <returns></returns>
    private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "") {
        // Check if it contains any Invalid Characters.
        if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1) {
            try {
                // If path is relative take %IGXLROOT% as the base directory
                if (!Path.IsPathRooted(path)) {
                    if (string.IsNullOrEmpty(RelativePath)) {
                        // Exceptions handled by Path.GetFullPath
                        // ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
                        // 
                        // SecurityException The caller does not have the required permissions.
                        // 
                        // ArgumentNullException path is null.
                        // 
                        // NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\"). 
                        // PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.
    
                        // RelativePath is not passed so we would take the project path 
                        path = Path.GetFullPath(RelativePath);
    
                    } else {
                        // Make sure the path is relative to the RelativePath and not our project directory
                        path = Path.Combine(RelativePath, path);
                    }
                }
    
                // Exceptions from FileInfo Constructor:
                //   System.ArgumentNullException:
                //     fileName is null.
                //
                //   System.Security.SecurityException:
                //     The caller does not have the required permission.
                //
                //   System.ArgumentException:
                //     The file name is empty, contains only white spaces, or contains invalid characters.
                //
                //   System.IO.PathTooLongException:
                //     The specified path, file name, or both exceed the system-defined maximum
                //     length. For example, on Windows-based platforms, paths must be less than
                //     248 characters, and file names must be less than 260 characters.
                //
                //   System.NotSupportedException:
                //     fileName contains a colon (:) in the middle of the string.
                FileInfo fileInfo = new FileInfo(path);
    
                // Exceptions using FileInfo.Length:
                //   System.IO.IOException:
                //     System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
                //     directory.
                //
                //   System.IO.FileNotFoundException:
                //     The file does not exist.-or- The Length property is called for a directory.
                bool throwEx = fileInfo.Length == -1;
    
                // Exceptions using FileInfo.IsReadOnly:
                //   System.UnauthorizedAccessException:
                //     Access to fileName is denied.
                //     The file described by the current System.IO.FileInfo object is read-only.-or-
                //     This operation is not supported on the current platform.-or- The caller does
                //     not have the required permission.
                throwEx = fileInfo.IsReadOnly;
    
                if (!string.IsNullOrEmpty(Extension)) {
                    // Validate the Extension of the file.
                    if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase)) {
                        // Trim the Library Path
                        path = path.Trim();
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return true;
    
                }
            } catch (ArgumentNullException) {
                //   System.ArgumentNullException:
                //     fileName is null.
            } catch (System.Security.SecurityException) {
                //   System.Security.SecurityException:
                //     The caller does not have the required permission.
            } catch (ArgumentException) {
                //   System.ArgumentException:
                //     The file name is empty, contains only white spaces, or contains invalid characters.
            } catch (UnauthorizedAccessException) {
                //   System.UnauthorizedAccessException:
                //     Access to fileName is denied.
            } catch (PathTooLongException) {
                //   System.IO.PathTooLongException:
                //     The specified path, file name, or both exceed the system-defined maximum
                //     length. For example, on Windows-based platforms, paths must be less than
                //     248 characters, and file names must be less than 260 characters.
            } catch (NotSupportedException) {
                //   System.NotSupportedException:
                //     fileName contains a colon (:) in the middle of the string.
            } catch (FileNotFoundException) {
                // System.FileNotFoundException
                //  The exception that is thrown when an attempt to access a file that does not
                //  exist on disk fails.
            } catch (IOException) {
                //   System.IO.IOException:
                //     An I/O error occurred while opening the file.
            } catch (Exception) {
                // Unknown Exception. Might be due to wrong case or nulll checks.
            }
        } else {
            // Path contains invalid characters
        }
        return false;
    }
    

    【讨论】:

      【解决方案4】:

      认为现在回答为时已晚,但是... :) 如果路径带有卷名,您可以编写如下内容:

      using System;
      using System.Linq;
      using System.IO;
      
      // ...
      
      var drives = Environment.GetLogicalDrives();
      var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\\/]", "");
      var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
      if (drive != null) {
          var fileDirPath = filePath.Substring(drive.Length);
          if (0 < fileDirPath.Length) {
              if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
                  if (Path.Combine(drive, fileDirPath) != drive) {
                      // path correct and we can proceed
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        我不知道有什么开箱即用的东西可以为您验证所有这些,但是 .NET 中的 Path 类可以极大地帮助您。

        对于初学者来说,它有:

        char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters
        

        或:

        Path.GetPathRoot(string); // will return the root.
        

        【讨论】:

          【解决方案6】:

          您可以使用 System.Uri 类。 Uri 类不仅对 Web URL 有用,它还处理文件系统路径。使用 Uri.TryCreate 方法查找路径是否为 root,然后使用 IsLoopback 属性确定 Uri 是否引用本地计算机。

          这是一个简单的方法,它可以确定字符串是否是有效的、本地的和根文件路径。

          public bool IsPathValidRootedLocal(String pathString) {
              Uri pathUri;
              Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
              return isValidUri && pathUri != null && pathUri.IsLoopback;
          }
          

          我相信这会奏效。

          【讨论】:

          • 你还应该检查Uri.Schema是否是一个文件。
          • 此外,file:///a 之类的内容将被您的方法接受为有效路径。
          • 如果末尾有问号也不起作用。 C:\\foo\\bar??
          【解决方案7】:

          System.IO 命名空间中有几种方法可供您使用:

          Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
          Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
          Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.
          

          按照建议,您可以这样做:

          bool IsValidFilename(string testName) {
              string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
              Regex containsABadCharacter = new Regex(regexString);
              if (containsABadCharacter.IsMatch(testName)) {
                  return false;
              }
          
              // Check for drive
              string pathRoot = Path.GetPathRoot(testName);
              if (Directory.GetLogicalDrives().Contains(pathRoot)) {
                  // etc
              }
          
              // other checks for UNC, drive-path format, etc
          
              return true;
          }
          

          【讨论】:

          • 不会投反对票,但是在使用其他人的示例代码时,您确实应该给予信任,尤其是当它不是真正正确的时候。 stackoverflow.com/questions/62771/…
          • "regexString" 应该看起来更像: string regexStringPath = "[" + Regex.Escape(new string (System.IO.Path.GetInvalidPathChars())) + "]";
          • @"C:\\Windows" 是怎么回事(确实带有双反斜杠)?资源管理器说它不是一个有效的路径,但你没有检查这个。
          【解决方案8】:

          做就做;

          System.IO.FileInfo fi = null;
          try {
            fi = new System.IO.FileInfo(fileName);
          }
          catch (ArgumentException) { }
          catch (System.IO.PathTooLongException) { }
          catch (NotSupportedException) { }
          if (ReferenceEquals(fi, null)) {
            // file name is not valid
          } else {
            // file name is valid... May check for existence by calling fi.Exists.
          }
          

          要创建FileInfo 实例,该文件不需要存在。

          【讨论】:

          • 小心使用 FileInfo。任何字符串,即使它只是一个字母,也是构造函数中的有效参数,但简单地尝试 new FileInfo(pathTheuserEntered) 将导致 FileInfo 假定文件是相对于当前工作目录的,这可能不是你想要的。
          • 我使用 bOk = System.IO.Path.IsPathRooted(fileName); 增强了这个解决方案而不是 bOk = true;
          • 这不会捕获包含无效的“/”的文件名。
          • 您可以检查您的文件名是否包含 char[] badChars = Path.GetInvalidFileNameChars(); 所返回的数组中的任何字符;
          • 请注意,像\\drive\file.txt 这样的UNC 路径将需要很长时间来评估,因为构造函数会发送SMB 数据包来获取所有FileInfo 属性。
          【解决方案9】:

          使用System.IO namespacePath class 上的静态GetInvalidFileNameChars method 来确定文件名中哪些字符是非法的。

          要在路径中执行此操作,请在同一类上调用静态 GetInvalidPathChars method

          要确定路径的根是否有效,您可以在Path 类上调用静态GetPathRoot method 来获取根,然后使用Directory class 来确定它是否有效。然后就可以正常验证路径的其余部分了。

          【讨论】:

          • "此方法返回的数组不保证包含文件和目录名称中无效的 完整 字符集。" Remarks
          • 扩展 RobertP 上面所说的内容......单独使用 GetInvalidPathChars 并不是测试表示路径的字符串的有效性的完全正确的方法。此方法返回“控制”字符和“ >
          【解决方案10】:

          正如其他人所展示的那样,我很幸运地使用了正则表达式。

          要记住的一件事是,Windows 至少禁止某些包含合法字符的文件名。想到了几个:com、nul、prn。

          我现在没有它,但我有一个将这些文件名考虑在内的正则表达式。如果你愿意,我可以发布它,否则我相信你可以像我一样找到它:谷歌。

          -杰

          【讨论】:

            【解决方案11】:

            这将为您提供机器上的驱动器:

            System.IO.DriveInfo.GetDrives()
            

            这两种方法会让你检查坏字符:

            System.IO.Path.GetInvalidFileNameChars();
            System.IO.Path.GetInvalidPathChars();
            

            【讨论】:

              【解决方案12】:

              如果路径或文件名无效,一些 System.IO.Path 方法将抛出异常:

              • Path.IsPathRooted()
              • Path.GetFileName()

              http://msdn.microsoft.com/en-us/library/system.io.path_methods.aspx

              【讨论】:

              • 这似乎不是真的,至少在 Mono 中(例如在 Unity 中)。我使用的是“Bogus\\Invalid!/No:Such?File!*@#!”的虚假路径,IsPathRooted 返回 true,GetFileName 返回斜杠后的部分,FileInfo 完全无法抛出异常。 (但是在目录上调用 GetDirectories 确实会引发异常,所以也许这就是我的答案。)
              • 那行不通。 Path.GetFileName("*xxx?") 将返回 "*xxx?"无一例外。也不要忘记对于新文件不正确的保留文件名。在 Windows 中,这些是“prn”、“con”等。
              • 这个答案是错误的。
              【解决方案13】:

              可能最糟糕的方法是构建一个自定义方法,混合正则表达式和文件系统上的小查找(例如,查看驱动器)

              【讨论】:

                【解决方案14】:

                即使文件名是有效的,您可能仍想touch 以确保用户具有写入权限。

                如果您不会在短时间内用数百个文件敲打磁盘,我认为创建一个空文件是一种合理的方法。

                如果你真的想要更轻的东西,比如检查无效字符,然后将你的文件名与 Path.GetInvalidFileNameChars() 进行比较。

                【讨论】:

                  猜你喜欢
                  • 2012-12-06
                  • 2018-11-23
                  • 2014-10-21
                  • 2015-09-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-08-05
                  • 1970-01-01
                  • 2015-12-30
                  相关资源
                  最近更新 更多