Перевірте, чи вказано повний шлях


104

Чи існує спосіб перевірити, чи заданий шлях є повним шляхом? Зараз я роблю це:

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

Але повинен бути більш елегантний спосіб перевірити це?

Відповіді:


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

4
Другий шлях не є абсолютним, проте він укорінений. Провідна риса вказує корінь системи.
detaylor

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включає гучність

У таких сценаріях, як той, який ставив ОП, тому він може бути більш підходящим, ніж умови попередніх відповідей. На відміну від вищевказаної умови:

  • 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 -> Розробити -> Настільні технології -> Доступ до даних і зберігання -> Локальні файлові системи - -> Управління файлами -> Про управління файлами -> Створення, видалення та підтримка файлів -> Іменування файлів, шляхів та просторів імен -> Повністю кваліфіковані та відносні шляхи

Для функцій API Windows, що управляють файлами, імена файлів часто можуть бути відносно поточного каталогу, тоді як для деяких API потрібен повністю кваліфікований шлях. Ім'я файлу відносно поточного каталогу, якщо воно не починається з одного з наступних:

  • Назва UNC будь-якого формату, яка завжди починається з двох зворотних косих символів ("\"). Для отримання додаткової інформації дивіться наступний розділ.
  • Дисковий позначення зі зворотною косою рисою, наприклад "C: \" або "d: \".
  • Один зворотний кут, наприклад, "\ каталог" або "\ file.txt". Це також називається абсолютним шляхом.

Якщо ім'я файлу починається лише з позначення диска, але не з косою рисою після двокрапки, це інтерпретується як відносний шлях до поточного каталогу на диску з вказаною літерою. Зауважте, що поточний каталог може бути або не бути кореневою каталогом залежно від того, для чого він був встановлений під час останньої операції "зміни каталогу" на цьому диску. Приклади такого формату:

  • "C: tmp.txt" посилається на файл з назвою "tmp.txt" у поточному каталозі на накопичувачі C.
  • "C: tempdir \ tmp.txt" посилається на файл у підкаталозі до поточного каталогу на диску CD.

[...]


3
Мені подобається, що це не кидає для недійсних шляхів, але повертає істинність для таких шляхів, як "C:" та "C: dir", які вирішуються GetFullPath за допомогою поточного каталогу (тому вони не є абсолютними). Опублікував відповідь, яка для них повертає помилкову.
EM0

@ EM0 - Дякую! Ви просто чогось навчили мене. :)
weir

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 'повертає істинні відносні шляхи (не обов’язково абсолютні шляхи)
bitcoder

GetFullPathотримує доступ до файлової системи та може викинути ряд можливих винятків. Дивіться мою відповідь ( stackoverflow.com/a/35046453/704808 ) щодо альтернативи, яка все-таки забезпечує повний шлях.
привіт

11

Спираючись на відповідь weir : це не вказує на недійсні шляхи, але також повертається 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 шлях не є відносним, якщо він починається з "Один зворотний кут, наприклад," \ каталог "або" \ файл .txt ". Це також називається абсолютним шляхом. "
weir

1
Гарна думка! Схоже, моя термінологія була вимкнена. Коли я сказав «абсолютний шлях», я дійсно думав про те, що МС називає «повним шляхом». Я змінив ім'я та додав для цього тестовий випадок.
EM0

1
Дякую за цю відповідь, мені це дуже допомогло. Однак зауважте, що для шляху UNC, такого як \\ сервер \, метод повертає true, але це викине виняток, якщо потім викличете Directory.Exists (path) (System.ArgumentException: 'Шлях UNC повинен мати форму \\ сервер \ поділитися. ')
Карл

2
Приємно бачити людей, які все ще користуються цим і знаходять нові крайові корпуси @Carl Оновили код і протестували на це!
EM0

6

Щоб перевірити, чи є шлях повністю кваліфікованим (MSDN) :

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

Це трохи простіше, ніж те, що вже було запропоновано, і воно все ще повертає помилку для шляхів, що відносяться до диска, як 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\..\fooабоC:\foo\.\.\.
sergtk

1

Викличте таку функцію:

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

MSDN doc: Path.IsPathFullyQualified метод

Корисний цитата з MSDN doc наступним чином:

Цей метод обробляє контури, які використовують альтернативний роздільник каталогів. Часта помилка вважає, що вкорінені шляхи ( IsPathRooted (String) ) не є відносними. Наприклад, "C: a" - відносний диск, тобто вирішено проти поточної каталогів для C: (вкорінене, але відносне). "C: \ a" вкорінюється і не є відносним, тобто поточний каталог не використовується для зміни шляху.


0

Я не дуже впевнений, що ви маєте на увазі під повним шляхом (хоча, маючи на увазі приклад, який ви маєте на увазі не відносне від кореня далі), ну, ви можете використовувати клас Path, щоб допомогти вам у роботі з шляхами фізичної файлової системи, які повинні охоплювати ви для більшості випадків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.