检查路径是否有效。

132

我在思考:我正在寻找一种方法来验证给定的路径是否有效。 (注意:我不想检查文件是否存在!我只想证明路径的有效性-因此,如果文件可能存在于该位置)。

问题是,在.Net API中找不到任何东西。 由于Windows支持许多格式和位置,我宁愿使用一些微软本地的东西。

由于函数应该能够针对以下内容进行检查:

  • 相对路径(./)
  • 绝对路径(c:\tmp)
  • UNC-路径(\some-pc\c$)
  • NTFS限制,如完整路径1024个字符-如果我没有记错,超过路径会使文件对许多 内部Windows功能无法访问。使用Explorer重命名仍然有效
  • 卷GUID路径:“\?\Volume{GUID}\somefile.foo

有人有这样的函数吗?


12个回答

68

尝试使用Uri.IsWellFormedUriString()函数:

  • 字符串未正确转义。

  http://www.example.com/path???/file name
  • 该字符串是表示隐式文件 Uri 的绝对 Uri。

  •   c:\\directory\filename
    
  • 该字符串是一个绝对URI,但路径前缺少斜杠。

  •   file://c:/directory/filename
    
  • 即使它们被视为正斜杠,该字符串仍包含未转义的反斜杠。

  •   http:\\host/path/file
    
  • 该字符串代表一个层次结构化的绝对Uri,并且不包含“://”。

  •   www.example.com/path/file
    
  • Uri.Scheme的解析器表明原始字符串格式不正确。

  •   The example depends on the scheme of the URI.
    

    13
    对于@"foo\bar\baz",这会返回false,但这是一个完全有效的相对路径... - Thomas Levesque
    5
    Thomas: 你指定了什么UriKind?你可以使用Absolute、Relative或者AbsoluteOrRelative。 - Dan Gøran Lunde
    3
    即使将UriKind设为Relative或AbsoluteOrRelative,它也无法处理像Thomas所提到的相对路径。我最终使用了Patko的答案,它适合我的用途。 - JohnnyM
    1
    这并不适用于所有这些例子。 https://msdn.microsoft.com/zh-cn/library/system.uri.iswellformeduristring(v=vs.110).aspx 文档说明: 如果出现以下任何条件,则认为字符串格式不正确,导致该方法返回 false: 字符串未正确转义。 http://www.contoso.com/path???/file name 字符串是表示隐式文件 Uri 的绝对 Uri。 c:\directory\filename ... - Xav987
    5
    对于一个完全正确的文件路径,返回false。 - Evgeni Petrov
    显示剩余4条评论

    31

    1
    使用“LamdaComplex”在同一主题中发布的解决方案似乎更准确:https://dev59.com/E3RC5IYBdhLWcg3wD83r#11636052 - Xav987

    13

    对于以下代码,我没有遇到任何问题。(相对路径必须以'/'或'\'开头)。

    private bool IsValidPath(string path, bool allowRelativePaths = false)
    {
        bool isValid = true;
    
        try
        {
            string fullPath = Path.GetFullPath(path);
    
            if (allowRelativePaths)
            {
                isValid = Path.IsPathRooted(path);
            }
            else
            {
                string root = Path.GetPathRoot(path);
                isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
            }
        }
        catch(Exception ex)
        {
            isValid = false;
        }
    
        return isValid;
    }
    
    例如,以下内容将返回 false:
    IsValidPath("C:/abc*d");
    IsValidPath("C:/abc?d");
    IsValidPath("C:/abc\"d");
    IsValidPath("C:/abc<d");
    IsValidPath("C:/abc>d");
    IsValidPath("C:/abc|d");
    IsValidPath("C:/abc:d");
    IsValidPath("");
    IsValidPath("./abc");
    IsValidPath("./abc", true);
    IsValidPath("/abc");
    IsValidPath("abc");
    IsValidPath("abc", true);
    

    这些将返回true:

    IsValidPath(@"C:\\abc");
    IsValidPath(@"F:\FILES\");
    IsValidPath(@"C:\\abc.docx\\defg.docx");
    IsValidPath(@"C:/abc/defg");
    IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
    IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
    IsValidPath(@"C:\\\\\abc////////defg");
    IsValidPath(@"/abc", true);
    IsValidPath(@"\abc", true);
    

    6
    您可以尝试这段代码:
    try
    {
      Path.GetDirectoryName(myPath);
    }
    catch
    {
      // Path is not valid
    }
    

    我不确定它是否涵盖了所有情况...


    6
    private bool IsValidPath(string path)
    {
        Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
        if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
        string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
        strTheseAreInvalidFileNameChars += @":/?*" + "\"";
        Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
        if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
            return false;
    
        DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
        if (!dir.Exists)
            dir.Create();
        return true;
    }
    

    11
    创建一个文件夹是一个令人不满的副作用,而你原本以为这个布尔值只是为了检查一个字符串。 - HackSlash

    4

    这里有很多好的解决方案,但是由于没有检查路径是否根据现有驱动器进行了根化,所以这里提供另一种解决方案:

    private bool IsValidPath(string path)
    {
        // Check if the path is rooted in a driver
        if (path.Length < 3) return false;
        Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
        if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    
        // Check if such driver exists
        IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
        if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;
    
        // Check if the rest of the path is valid
        string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
        InvalidFileNameChars += @":/?*" + "\"";
        Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
        if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
            return false;
        if (path[path.Length - 1] == '.') return false;
    
        return true;
    }
    

    这个解决方案不会考虑相对路径。


    2
    它通过了我的测试,只是缺少空值检查...可以在第一个条件中添加if (path == null || path.Length < 3) return false; - Muhammad Sulaiman
    1
    另一件事是,由于“d”是小写字母,因此d:\folder1\被认为是无效路径,我通过在函数开头添加path = path?.ToUpper();来解决这个问题。 - Muhammad Sulaiman

    1

    这个函数接受一个路径参数,该参数可以等同于有效的相对路径。

    string path = "yourPath";
    bool pathIsValid = null;
    try
    { 
        Path.GetFullPath(path);
        pathIsValid = true;
    }
    catch
    {
        pathIsValid = false;
    }
    

    1

    我最接近的方法是尝试创建它,并查看是否成功。


    1
    System.IO.Path.GetInvalidPathChars();获取无效字符,然后检查您的字符串(目录路径)是否包含这些字符。

    4
    这并不完全正确。"C:\new.folder"是有效的,而"C:\newfolder."则无效。 "."是路径/文件名中的有效字符,但不能出现在URI的末尾。 - claudekennilol

    -1
    private bool IsValidPath(string path)
    {
        Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    
        if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
        {
            return false;
        }
    
        if (!driveCheck.IsMatch(path.Substring(0, 3)))
        {
            return false;
        }
    
        var x1 = (path.Substring(3, path.Length - 3));
        string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
        strTheseAreInvalidFileNameChars += @":?*";
        Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    
        if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        {
            return false;
        }
    
        var driveLetterWithColonAndSlash = Path.GetPathRoot(path);
    
        if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
        {
            return false;
        }
    
        return true;
    }
    

    1
    x1的目的是什么? - JayJay

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接