Проверьте, указан ли полный путь


есть ли способ проверить, является ли данный путь полным путем? Прямо сейчас я делаю это:

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

но должен быть более элегантный способ проверить это?

8 79

8 ответов:

попробуйте использовать 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]\foo"
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

вышеуказанное условие:

  • не требует разрешения файловой системы
  • возвращает false в большинстве случаев, когда формате path недопустимо (а не выбрасывать исключение)
  • возвращает true только если path С

в сценариях, подобных тому, который задал ОП, он может быть более подходящим, чем условия в более ранних ответах. В отличие от вышеперечисленного состояние:

  • 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);
}

EDIT: EM0 сделал хороший комментарий и альтернативный ответ обращаясь к любопытному случаю таких путей, как C: и C:dir. Чтобы помочь решить, как вы можете обрабатывать такие пути, вы можете взять глубокое погружение в MSDN --> Windows desktop applications -->разработки -->технологии для настольных ПК -->доступ к данным и их хранение -->Локальные Файловые Системы -->Управления -->Об Управлении -->создание, удаление и сохранение файлов -->именование файлов, путей и пространств имен -->полное и относительное Пути

для функций Windows API, которые управляют файлами, имена файлов часто могут быть относительно текущего каталога, в то время как некоторые API требуют полностью квалифицированный путь. Имя файла относится к текущему каталогу, если оно не начинается с одного из следующих:

  • UNC-имя любого формата, которое всегда начинается с двух символов обратной косой черты ("\"). Дополнительные сведения см. В следующем разделе.
  • диск обозначение С обратной косой чертой, например "C:\" или "d:\".
  • одна обратная косая черта, например, "\directory" или "\file.формат txt." Это также называется абсолютным путем.

если имя файла начинается с обозначения диска, но не обратная косая черта после двоеточия интерпретируется как относительный путь к текущий каталог на диске с указанной буквы. Заметить что текущий каталог может быть или не быть корневым каталогом в зависимости на что было установлено во время последней "смены каталога" операция на этом диске. Примеры этого формата следующие:

  • " C: tmp.txt " относится к файлу с именем "tmp.txt" в текущем каталоге на диске C.
  • "C:tempdir\tmp.txt " относится к файлу в подкаталоге к текущему каталогу на диске C.

[...]

попробовать

System.IO.Path.IsPathRooted(template)

работает для UNC-путей, а также локальных.

например.

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

старый вопрос, но еще один применимый ответ. Если вам нужно убедиться, что Том включен в локальный путь, вы можете использовать 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
}

дом на плотинаответ: это не бросает для недопустимых путей, но и возвращает false на пути как "C:", в "каталог" и "путь\".

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

    var 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;

    return !(pathRoot == path && pathRoot.StartsWith("\\") && pathRoot.IndexOf('\', 2) == -1); // A UNC server name without a share name (e.g "\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);
}

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):

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]));
}

Я не уверен, что вы подразумеваете под полный путь (хотя если исходить из примера вы имеете в виду не относительный от корня и далее), ну, вы можете использовать путь класс, чтобы помочь вам в работе с физическими путями файловой системы, которая должна охватывать вас для большинства случаев.

это решение я использую

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