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

xzabzqsa  于 2022-12-01  发布在  .NET
关注(0)|答案(3)|浏览(181)

给定一个路径,我需要知道它是否是完全限定路径(绝对路径)。
我知道有一个名为System.IO.Path.IsPathRooted的方法,但对于如下路径,该方法返回true:

  • C:文件
  • /文件

我看到了一个名为IsPathFullyQualified的方法,我对此很感兴趣,请参见here,但不幸的是,它似乎在.NET Framework 4.5下无法识别。那么,.NET 4.5是否有等效的方法?

vhmi4jdf

vhmi4jdf1#

**完整免责声明:**我没有写这个代码我自己,没有任何权利。这是基于.NET核心源代码由微软。更多信息如下。
**TL;DR:**对于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 Core Source Browser是公开的,经过调整可以与.NET Framework一起使用,并转换为VB .NET。
.NET核心的IsPathFullyQualified()方法使用名为IsPartiallyQualified()的内部方法来检查路径是否完全限定(而不是部分限定)。该内部方法对于不同的操作系统具有不同的逻辑。这是上述代码所基于的Windows版本。

用法:

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

6jjcrrmo2#

下面是另一种可能的方法,用于确定Path是否完全限定且有效。
此方法(*)尝试使用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
  • 这个方法会传回Named Tuple:支持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
yfjy0ee7

yfjy0ee73#

我偶然发现这个寻找使用这种方法,但意识到其他答案过于复杂。
我在这里看了MS的源代码:https://source.dot.net/#System.Private.CoreLib/Path.cs,3b4bff90471c3a68
请访问以下网址:http://referencesources.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';

相关问题