我知道有一个叫做
System.IO.Path.IsPathRooted
的方法,但是这个方法对于以下路径也会返回true:
- C:Documents
- /Documents
IsPathFullyQualified
的方法,我很感兴趣,可以在这里看到,但不幸的是,在.NET Framework 4.5下似乎无法识别。那么在.NET 4.5中有没有相应的方法呢?完全免责声明:本人并未亲自编写此代码,也不拥有任何权利。此代码基于微软的.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
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
我发现这个方法后想要使用它,但发现其他答案过于复杂。
我查看了微软的源代码,链接如下:https://source.dot.net/#System.Private.CoreLib/Path.cs,3b4bff90471c3a68和 https://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';