【问题标题】:How to determine if a path is fully qualified?如何确定路径是否完全合格?
【发布时间】:2020-02-23 19:16:08
【问题描述】:

给定一条路径,我需要知道它是否是完全限定路径(绝对路径)。

我知道有一个名为 System.IO.Path.IsPathRooted 的方法,但这对于以下路径返回 true:

  • C:文档
  • /文档

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

【问题讨论】:

    标签: .net vb.net .net-4.5


    【解决方案1】:

    完全免责声明:此代码不是我自己编写的,也不拥有任何权利。这是基于 Microsoft 的 .NET Core Source。更多信息如下。

    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
    
        Friend 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
    
        Friend Shared Function IsDirectorySeparator(c As Char) As Boolean
            Return c = Path.DirectorySeparatorChar OrElse c = Path.AltDirectorySeparatorChar
        End Function
    
        Friend 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
    

    这段代码(和 cmets)从何而来?

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

    .NET Core 的 IsPathFullyQualified() method 使用称为 IsPartiallyQualified() 的内部方法来检查路径是否完全限定(不是部分限定)。该内部方法对于不同的操作系统具有不同的逻辑。 This是上面代码所基于的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 Source code 中看到PrivateParseMinimal() 方法执行了许多测试来验证路径并检查DosPath 是否已被root。

      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
      

      【讨论】:

        【解决方案3】:

        我遇到了这个希望使用这种方法,但意识到其他答案过于复杂。

        我在这里查看了MS的源代码:https://source.dot.net/#System.Private.CoreLib/Path.cs,3b4bff90471c3a68

        这里: https://referencesource.microsoft.com/#mscorlib/system/io/path.cs,807960f08fca497d

        我注意到在第二个链接中,检查 IsPathRooted 的方法之一是检查:(length &gt;= 2 &amp;&amp; path[1] == VolumeSeparatorChar)。我只是将检查调整为一个充实的方法。

        .Net 源代码(链接 1)本质上是 IsPathFullyQualified =&gt; !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';
        

        【讨论】:

          猜你喜欢
          • 2011-04-05
          • 2012-07-29
          • 2014-06-27
          • 1970-01-01
          • 2015-07-07
          • 2016-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多