Проверьте, указан ли полный путь
Есть ли способ проверить, является ли данный путь полным путем? Прямо сейчас я делаю это:
if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local assembly
{
}
Но должен ли быть более элегантный способ проверить это?
Ответы
Ответ 1
Попробуйте использовать 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"
Ответ 2
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);
}
ОБНОВЛЕНИЕ: EM0 сделал хороший комментарий и альтернативный ответ, обращаясь к любопытному случаю путей, таких как C:
и C:dir
. Чтобы решить, как вы можете обрабатывать такие пути, вы можете глубоко погрузиться в MSDN → Настольные приложения Windows → Разработка → Технологии рабочего стола → Доступ к данным и хранение → Локальные файловые системы - → Управление файлами → Об управлении файлами → Создание, удаление и ведение файлов → Именование файлов, путей и пространств имен → Полностью квалифицированные и относительные пути
Для функций API Windows, которые манипулируют файлами, имена файлов часто могут быть относительно текущего каталога, в то время как некоторые API требуют полностью квалифицированный путь. Имя файла относительно текущего каталога, если оно не начинается с одного из следующих:
- UNC-имя любого формата, которое всегда начинается с двух символов обратной косой черты ("\"). Для получения дополнительной информации см. следующий раздел.
- Обозначение диска с обратной косой чертой, например "C: \" или "d: \".
- Единственная обратная косая черта, например, "\ directory" или "\ file.txt". Это также называется абсолютным путем.
Если имя файла начинается только с обозначения диска, а не с обратная косая черта после двоеточия, это интерпретируется как относительный путь к текущий каталог на диске с указанной буквой. Обратите внимание, что текущий каталог может или не может быть корневым каталогом в зависимости на что он был установлен во время самой последней "смены каталога" операция на этом диске. Примеры этого формата:
- "C: tmp.txt" относится к файлу с именем "tmp.txt" в текущем каталоге на диске C.
- "C: tempdir\tmp.txt" относится к файлу в подкаталоге текущего каталога на диске C.
[...]
Ответ 3
Try
System.IO.Path.IsPathRooted(template)
Работает как для UNC-путей, так и для локальных.
например.
Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory") // returns true
Path.IsPathRooted(@"C:\\MyDirectory") // returns true
Ответ 4
Старый вопрос, но еще один применимый ответ. Если вам необходимо убедиться, что том включен в локальный путь, вы можете использовать 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
}
Ответ 5
Основываясь на ответе 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, например "/путь" является абсолютным в Linux, но не в Windows.
Unit тест:
[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);
}
}
Ответ 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 does not 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 default data stream.
&& IsValidDriveChar(path[0]));
}
Ответ 7
Это решение, которое я использую
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
Ответ 8
Я не совсем уверен, что вы подразумеваете под полным путем (хотя предполагается, что из примера вы имеете в виду не относительный от корня и далее), ну, вы можете использовать Path, чтобы помочь вам в работе с физическими путями файловой системы, которые должны охватывать вас в большинстве случаев.
Ответ 9
Вызовите следующую функцию:
Path.IsPathFullyQualified(@"c:\foo")
MSDN doc: Path.IsPathFullyQualified Method
Ниже приводится полезная ссылка на документ MSDN:
Этот метод обрабатывает пути, которые используют альтернативный разделитель каталогов. Часто ошибочно полагать, что укоренившиеся пути (IsPathRooted (String)) не являются относительными. Например, "C: a" - это диск относительный, то есть он разрешен относительно текущего каталога для C: (укорененный, но относительный). "C:\a" является корнем и не является относительным, то есть текущий каталог не используется для изменения пути.