如何确定路径是否是完全限定的?

3
给定一个路径,我需要知道它是否是完全限定路径(绝对路径)。
我知道有一个叫做System.IO.Path.IsPathRooted的方法,但是这个方法对于以下路径也会返回true:
  • C:Documents
  • /Documents
我见过一个叫做IsPathFullyQualified的方法,我很感兴趣,可以在这里看到,但不幸的是,在.NET Framework 4.5下似乎无法识别。那么在.NET 4.5中有没有相应的方法呢?
3个回答

3

完全免责声明:本人并未亲自编写此代码,也不拥有任何权利。此代码基于微软的.NET Core源代码。更多信息请参见下文。

简述:对于Windows系统,您可以将以下类添加到您的项目中,然后调用PathEx.IsPathFullyQualified()来检查路径是否完全合格:

Public Class PathEx
    Public Shared Function IsPathFullyQualified(path As String) As Boolean
        If path Is Nothing Then
            Throw New ArgumentNullException(NameOf(path))
        End If

        Return Not IsPartiallyQualified(path)
    End Function

    Private Shared Function IsPartiallyQualified(path As String) As Boolean
        If path.Length < 2 Then
            ' It isn't fixed, it must be relative.  There is no way to specify a fixed
            ' path with one character (or less).
            Return True
        End If

        If IsDirectorySeparator(path.Chars(0)) Then
            ' There is no valid way to specify a relative path with two initial slashes or
            ' \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
            Return Not (path.Chars(1) = "?"c OrElse IsDirectorySeparator(path.Chars(1)))
        End If

        ' The only way to specify a fixed path that doesn't begin with two slashes
        ' is the drive, colon, slash format- i.e. C:\
        Return Not ((path.Length >= 3) AndAlso
                    (path.Chars(1) = IO.Path.VolumeSeparatorChar) AndAlso
                    IsDirectorySeparator(path.Chars(2)) AndAlso
                    IsValidDriveChar(path.Chars(0)))
        '           ^^^^^^^^^^^^^^^^
        ' To match old behavior we'll check the drive character for validity as
        ' the path is technically not qualified if you don't have a valid drive.
        ' "=:\" is the "=" file's default data stream.
    End Function

    Private Shared Function IsDirectorySeparator(c As Char) As Boolean
        Return c = Path.DirectorySeparatorChar OrElse c = Path.AltDirectorySeparatorChar
    End Function

    Private Shared Function IsValidDriveChar(value As Char) As Boolean
        Return (value >= "A"c AndAlso value <= "Z"c) OrElse
               (value >= "a"c AndAlso value <= "z"c)
    End Function
End Class

这段代码(和注释)来自哪里?

这是从公开可用的.NET Core Source Browser中提取出来的,经过适应以适用于.NET Framework,并转换为VB.NET。

.NET Core的IsPathFullyQualified()方法使用名为IsPartiallyQualified()的内部方法来检查路径是否完全限定(而不是部分限定)。该内部方法对于不同的操作系统具有不同的逻辑。这个是基于上述代码的Windows版本。

用法:

Console.WriteLine(PathEx.IsPathFullyQualified("C:Documents"))    ' False
Console.WriteLine(PathEx.IsPathFullyQualified("/Documents"))     ' False
Console.WriteLine(PathEx.IsPathFullyQualified("C:\Documents"))   ' True

2
这里有另一种确定路径是否完全合格且有效的可能方法。
该方法(*)尝试使用Uri.TryCreate()从提供的路径生成Uri。当此方法成功时,它会检查非公共IsDosPath属性,该属性在解析新Uri时由Uri类内部设置,以确定它是否有效以及表示何种资源。
您可以在.Net源代码中看到PrivateParseMinimal()方法执行多个测试以验证路径,并检查是否根为DosPath
Imports System.Reflection

Private Function PathIsFullyQualified(path As String) As (Valid As Boolean, Parsed As String)
    Dim flags = BindingFlags.GetProperty Or BindingFlags.Instance Or BindingFlags.NonPublic
    Dim uri As Uri = Nothing
    If Uri.TryCreate(path, UriKind.Absolute, uri) Then
        Dim isDosPath = CBool(uri.GetType().GetProperty("IsDosPath", flags).GetValue(uri))
        Return (isDosPath, uri.LocalPath)
    End If
    Return (False, String.Empty)
End Function

* 此方法返回一个命名元组:自Visual Basic 2017起支持

我测试了以下路径;当我假设它们应该时,它们都返回False,除了"file://c:/Documents":,但PathIsFullyQualified方法也返回相应的本地路径c:\Documents:

Dim isOk1 = PathIsFullyQualified("C:Documents")            'False
Dim isOk2 = PathIsFullyQualified("/Documents")             'False
Dim isOk3 = PathIsFullyQualified("file://c:/Documents")    'True  => isOk3.Parsed = "c:\Documents"
Dim isOk4 = PathIsFullyQualified("\\Documents")            'False
Dim isOk5 = PathIsFullyQualified("..\Documents")           'False
Dim isOk6 = PathIsFullyQualified(".\Documents")            'False
Dim isOk7 = PathIsFullyQualified("\Documents")             'False
Dim isOk8 = PathIsFullyQualified("//Documents")            'False
Dim isOk9 = PathIsFullyQualified(".Documents")             'False
Dim isOkA = PathIsFullyQualified("..Documents")            'False
Dim isOkB = PathIsFullyQualified("http://C:/Documents")    'False
Dim isOkC = PathIsFullyQualified("Cd:\Documents")          'False
Dim isOkD = PathIsFullyQualified("1:\Documents")           'False
Dim isOkE = PathIsFullyQualified("Z:\\Another Path//docs") 'True => isOkE.Parsed = "Z:\Another Path\docs"
Dim isOkF = PathIsFullyQualified(":\\Another Path//docs")  'False

1

我发现这个方法后想要使用它,但发现其他答案过于复杂。

我查看了微软的源代码,链接如下:https://source.dot.net/#System.Private.CoreLib/Path.cs,3b4bff90471c3a68https://referencesource.microsoft.com/#mscorlib/system/io/path.cs,807960f08fca497d

我注意到在第二个链接中,检查是否为 IsPathRooted 的其中一种方法是通过检查此内容:(length >= 2 && path[1] == VolumeSeparatorChar)。我简单地将该检查适应为一个完整的方法。

.Net 源代码(链接1)本质上是 IsPathFullyQualified => !IsPathRooted,我认为这并不够严格。所以这是我的替代方案。

public static bool IsPathFullyQualified(string path)
{
    if (path == null)
        throw new ArgumentNullException(nameof(path));
    return path.Length >= 3 && path[1] == System.IO.Path.VolumeSeparatorChar && ( path[2] == System.IO.Path.DirectorySeparatorChar | path[2] == System.IO.Path.AltDirectorySeparatorChar );
}

编辑:我意识到上述简短的方法不接受UNC路径。因此,更新版本(承认这只是通过消除IsPartiallyQualified方法缩短原始答案的版本)如下:

public static bool IsPathFullyQualified(string path)
        {
            if (path == null) throw new ArgumentNullException(nameof(path));
            if (path.Length < 2) return false; //There is no way to specify a fixed path with one character (or less).
            if (path.Length == 2 && IsValidDriveChar(path[0]) && path[1] == System.IO.Path.VolumeSeparatorChar) return true; //Drive Root C:
            if (path.Length >= 3 && IsValidDriveChar(path[0]) &&  path[1] == System.IO.Path.VolumeSeparatorChar && IsDirectorySeperator(path[2])) return true; //Check for standard paths. C:\
            if (path.Length >= 3 && IsDirectorySeperator(path[0]) && IsDirectorySeperator(path[1])) return true; //This is start of a UNC path
            return false; //Default
        }

        private static bool IsDirectorySeperator(char c) => c == System.IO.Path.DirectorySeparatorChar | c == System.IO.Path.AltDirectorySeparatorChar;
        private static bool IsValidDriveChar(char c) => c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';

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