检查是否给出完整路径


104

有没有一种方法可以检查给定路径是否为完整路径?现在我正在这样做:

if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local assembly
{
}

但是,必须有更优雅的方法来检查这一点吗?

Answers:


141

尝试使用System.IO.Path.IsPathRooted?它还返回true绝对路径。

System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"

14
第二个例子怎么成为绝对路径?
om471987

3
第二条路径不是绝对路径,但是它是扎根的。前导斜杠表示系统的根。
detaylor '04

3
@SmirkinGherkin那么根路径和绝对路径之间有什么区别?
杰森·阿克森

1
请参阅我的答案(stackoverflow.com/a/35046453/704808),以确保在确保完整路径的同时,还保留以下优点IsPathRooted:避免访问文件系统或为无效输入抛出异常。

1
@ daniel,IIRC,它被包括来表明该路径不必是要使用的有效路径IsPathRooted,它当然并不重要。GetFullPath包括了该行,以便可以观察到所评估的路径
detaylor

30
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

以上条件:

  • 不需要文件系统权限
  • false在大多数情况下会返回path无效(而不是引发异常)
  • true仅在path包含音量的情况下返回

因此,在像OP那样的场景中,它可能比早期答案中的条件更合适。与上述条件不同:

  • path == System.IO.Path.GetFullPath(path)false在这些情况下抛出异常而不是返回:
    • 呼叫者没有所需的权限
    • 系统无法检索绝对路径
    • 路径包含一个不属于卷标识符的冒号(“:”)
    • 指定的路径,文件名或两者都超过了系统定义的最大长度
  • System.IO.Path.IsPathRooted(path)true如果path以单个目录分隔符开头,则返回。

最后,这是一个包装上述条件并取消其余可能的异常的方法:

public static bool IsFullPath(string path) {
    return !String.IsNullOrWhiteSpace(path)
        && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
        && Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}

编辑:EM0取得了良好的意见和备选答案解决的路径一样好奇的情况下C:C:dir。为了帮助您决定如何处理这些路径,您可能需要深入研究MSDN-> Windows桌面应用程序 -> 开发 -> 桌面技术 -> 数据访问和存储 -> 本地文件系统 - -> 文件管理 -> 关于文件管理 -> 创建,删除和维护文件 -> 命名文件,路径和命名空间 -> 完全限定与相对路径

对于操作文件的Windows API函数,文件名通常可以相对于当前目录,而某些API需要完全限定的路径。如果文件名不是以下列之一开头,则它是相对于当前目录的:

  • 任意格式的UNC名称,始终以两个反斜杠字符(“ \”)开头。有关更多信息,请参见下一节。
  • 带有反斜杠的磁盘标识符,例如“ C:\”或“ d:\”。
  • 单个反斜杠,例如“ \ directory”或“ \ file.txt”。这也称为绝对路径。

如果文件名仅以磁盘标识符开头,而不以冒号后的反斜杠开头,则将其解释为驱动器上具有指定字母的当前目录的相对路径。请注意,当前目录可能是根目录,也可能不是根目录,具体取决于在该磁盘上进行最新“更改目录”操作期间设置的根目录。此格式的示例如下:

  • “ C:tmp.txt”是指驱动器C上当前目录中的一个名为“ tmp.txt”的文件。
  • “ C:tempdir \ tmp.txt”是指驱动器C上当前目录的子目录中的文件。

[...]


3
我喜欢这样,它不会为无效路径抛出错误,但是对于诸如“ C:”和“ C:dir”之类的路径返回true,它们由GetFullPath使用当前目录解析(因此它们不是绝对的)。发布的答案针对这些返回false。
EM0

@ EM0-谢谢!你刚刚教我一些东西。:)

15

尝试

System.IO.Path.IsPathRooted(template)

适用于UNC路径以及本地路径。

例如

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory")  // returns true
Path.IsPathRooted(@"C:\\MyDirectory")  // returns true

13

旧问题,但还有一个更合适的答案。如果需要确保该卷包含在本地路径中,则可以使用System.IO.Path.GetFullPath()这样:

if (template == System.IO.Path.GetFullPath(template))
{
    ; //template is full path including volume or full UNC path
}
else
{
    if (useCurrentPathAndVolume)
        template = System.IO.Path.GetFullPath(template);
    else
        template = Assembly.GetExecutingAssembly().Location
}

3
这就是我所需要的,并且似乎更接近最初的问题,因为IsPathRooted对于相对路径(不一定是绝对路径)返回true
bitcoder 2015年

GetFullPath访问文件系统,并可能引发许多可能的异常。请参阅我的答案(stackoverflow.com/a/35046453/704808),以获得仍然可以确保完整路径的替代方法。

11

建立在的答案上:这不会抛出无效路径,还会返回false诸如“ C:”,“ C:dirname”和“ \ path”之类的路径。

public static bool IsFullPath(string path)
{
    if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
        return false;

    string pathRoot = Path.GetPathRoot(path);
    if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
        return false;

    if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
        return true; // Rooted and not a UNC path

    return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

请注意,这在Windows和Linux上返回不同的结果,例如,“ / path”在Linux上是绝对的,但在Windows上不是。

单元测试:

[Test]
public void IsFullPath()
{
    bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
    // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core

    // These are full paths on Windows, but not on Linux
    TryIsFullPath(@"C:\dir\file.ext", isWindows);
    TryIsFullPath(@"C:\dir\", isWindows);
    TryIsFullPath(@"C:\dir", isWindows);
    TryIsFullPath(@"C:\", isWindows);
    TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
    TryIsFullPath(@"\\unc\share", isWindows);

    // These are full paths on Linux, but not on Windows
    TryIsFullPath(@"/some/file", !isWindows);
    TryIsFullPath(@"/dir", !isWindows);
    TryIsFullPath(@"/", !isWindows);

    // Not full paths on either Windows or Linux
    TryIsFullPath(@"file.ext", false);
    TryIsFullPath(@"dir\file.ext", false);
    TryIsFullPath(@"\dir\file.ext", false);
    TryIsFullPath(@"C:", false);
    TryIsFullPath(@"C:dir\file.ext", false);
    TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path

    // Invalid on both Windows and Linux
    TryIsFullPath(null, false, false);
    TryIsFullPath("", false, false);
    TryIsFullPath("   ", false, false);
    TryIsFullPath(@"C:\inval|d", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}

private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
    Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");

    if (expectedIsFull)
    {
        Assert.AreEqual(path, Path.GetFullPath(path));
    }
    else if (expectedIsValid)
    {
        Assert.AreNotEqual(path, Path.GetFullPath(path));
    }
    else
    {
        Assert.That(() => Path.GetFullPath(path), Throws.Exception);
    }
}

好东西。我确实注意到msdn.microsoft.com/en-us/library/windows/desktop/…指出在Windows上,如果路径以'单个反斜杠开头(例如,“ \ directory”或“ \ file”),则该路径不是相对路径。文本”。这也称为绝对路径。

1
好点子!看来我的用语不对了。当我说“绝对路径”时,我真的在思考MS所谓的“完整路径”。我已经更改了名称并为此添加了一个测试用例。
EM0

1
感谢您的回答,对我有很大帮助。但是,请注意,对于UNC路径(例如\\ server \),该方法返回true,但是如果您随后调用Directory.Exists(path)(System.ArgumentException:'UNC路径应采用以下形式,则将引发异常: \\ server \ share。')
卡尔,

2
很高兴看到人们仍在使用它并找到新的边缘案例@Carl更新了代码并为此进行了测试!
EM0

6

要检查路径是否完全合格(MSDN)

public static bool IsPathFullyQualified(string path)
{
    var root = Path.GetPathRoot(path);
    return root.StartsWith(@"\\") || root.EndsWith(@"\");
}

它比已经提出的要简单一些,并且对于像的相对驱动器路径仍然返回false C:foo。它的逻辑直接基于MSDN的“完全限定”定义,我还没有发现任何不当的示例。


但是有趣的是,.NET Core 2.1似乎有一种Path.IsPathFullyQualified使用内部方法的新方法PathInternal.IsPartiallyQualified(链接位置截至2018-04-17准确)。

为了使后篇和更好地自我完善,这里是后者的实现,以供参考:

internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
    if (path.Length < 2)
    {
        // It isn't fixed, it must be relative.  There is no way to specify a fixed
        // path with one character (or less).
        return true;
    }

    if (IsDirectorySeparator(path[0]))
    {
        // 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 !(path[1] == '?' || IsDirectorySeparator(path[1]));
    }

    // 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 !((path.Length >= 3)
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2])
        // 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.
        && IsValidDriveChar(path[0]));
}

4

这是我使用的解决方案

public static bool IsFullPath(string path)
{
    try
    {
        return Path.GetFullPath(path) == path;
    }
    catch
    {
        return false;
    }
}

它的工作方式如下:

IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false

很有意思!例如,它很脆弱,必须匹配斜杠类型,但这很有希望。
尼古拉斯·彼得森

对于以下路径,它返回错误的结果:C:\foo\..\fooC:\foo\.\.\.
sergtk,

1

调用以下函数:

Path.IsPathFullyQualified(@"c:\foo")

MSDN文件:Path.IsPathFullyQualified方法

来自MSDN文档的有用引用如下:

此方法处理使用备用目录分隔符的路径。假定根路径(IsPathRooted(String))不是相对路径是一个经常犯的错误。例如,“ C:a”是相对于驱动器的,也就是说,它针对C:的当前目录解析(已root,但相对)。“ C:\ a”是根目录,而不是相对目录,即当前目录不用于修改路径。


0

我不太确定完整路径的含义(尽管从示例开始,假设从根开始是非相对的),那么您可以使用Path类来帮助您处理物理文件系统路径,这应该涵盖大多数情况下都是您。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.