Проверить, действителен ли путь

110

Мне просто интересно: я ищу способ проверить, действителен ли данный путь. (Примечание: я не хочу проверять, существует ли файл! Я хочу только подтвердить действительность пути - так, если файл может существовать в этом месте) .

Проблема в том, что я ничего не могу найти в API .Net. Из-за множества форматов и расположений, которые поддерживает Windows, я бы предпочел использовать что-то родное для MS.

Поскольку функция должна иметь возможность проверять:

  • Относительные пути (./)
  • Абсолютные пути (c: \ tmp)
  • UNC-пути (\ some-pc \ c $)
  • Ограничения NTFS, такие как полный путь 1024 символа. Если я не ошибаюсь, превышение пути сделает файл недоступным для многих внутренних функций Windows. Переименование в проводнике по-прежнему работает
  • Пути GUID тома: "\? \ Volume {GUID} \ somefile.foo

У кого-нибудь есть такая функция?

Тобиас Бошек
источник

Ответы:

58

Попробуйте Uri.IsWellFormedUriString():

  • Строка неправильно экранирована.

    http://www.example.com/path???/file name
  • Строка - это абсолютный Uri, который представляет неявный Uri файла.

    c:\\directory\filename
  • Строка представляет собой абсолютный URI без косой черты перед путем.

    file://c:/directory/filename
  • Строка содержит неэкранированные обратные косые черты, даже если они рассматриваются как прямые.

    http:\\host/path/file
  • Строка представляет собой иерархический абсолютный Uri и не содержит «: //».

    www.example.com/path/file
  • Парсер для Uri.Scheme указывает, что исходная строка не была правильно сформирована.

    The example depends on the scheme of the URI.
Абатищев
источник
9
Это возвращает false для @"foo\bar\baz", что является вполне допустимым относительным путем ...
Томас Левеск
5
Томас: Какой UriKind вы указали? Вы можете использовать Absolute, Relative или AbsoluteOrRelative.
Дэн Геран Лунде
1
Даже с UriKind как Relative или AbsoluteOrRelative он не работал для относительных путей, как упоминал Томас. Вместо этого я использовал ответ Патко, и он работает для моих целей.
JohnnyM
1
Я обнаружил, что такой путь, как \\ имя_компьютера \ имя каталога с пробелами \ имя_файла, вызывает исключение при использовании IsWellFformedUriString (вопреки моему первоначальному ожиданию), потому что пробелы не кодируются должным образом. Я обнаружил, что могу просто использовать конструктор Uri (string) в качестве проверки, таким образом, мне не нужно правильно кодировать строку перед проверкой.
quintessential5
3
Возвращает false для идеального пути к файлу.
Евгений Петров
7
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;

    DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
    if (!dir.Exists)
        dir.Create();
    return true;
}
Алекс Джолиг
источник
7

У меня не было проблем с приведенным ниже кодом. (Относительные пути должны начинаться с '/' или '\').

private bool IsValidPath(string path, bool allowRelativePaths = false)
{
    bool isValid = true;

    try
    {
        string fullPath = Path.GetFullPath(path);

        if (allowRelativePaths)
        {
            isValid = Path.IsPathRooted(path);
        }
        else
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
    }
    catch(Exception ex)
    {
        isValid = false;
    }

    return isValid;
}

Например, они вернут false:

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("./abc", true);
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", true);

И это вернет истину:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", true);
IsValidPath(@"\abc", true);
Искатель Дао
источник
3

Вы можете попробовать этот код:

try
{
  Path.GetDirectoryName(myPath);
}
catch
{
  // Path is not valid
}

Я не уверен, что он охватывает все случаи ...

Нимрод
источник
2

Самое близкое, что я пришел, - это попытаться создать его и посмотреть, удастся ли это.

Мартейн
источник
2

Здесь есть много хороших решений, но, поскольку ни одно из них не проверяет, коренится ли путь в существующем диске, вот еще один:

private bool IsValidPath(string path)
{
    // Check if the path is rooted in a driver
    if (path.Length < 3) return false;
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;

    // Check if such driver exists
    IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
    if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;

    // Check if the rest of the path is valid
    string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
    InvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;
    if (path[path.Length - 1] == '.') return false;

    return true;
}

Это решение не учитывает относительные пути.

Гарк Гарсия
источник
1

Получите недопустимые символы System.IO.Path.GetInvalidPathChars();и проверьте, содержит ли ваша строка (путь к каталогу) их или нет.

Умеш ЧИЛАКА
источник
3
Это не совсем так. «C: \ new.folder» допустимо, пока «C: \ newfolder». не является. '.' - допустимый символ для путей / имен файлов, но не в конце uri.
claudekennilol 07
0

Directory.Exists?

Markpsmith
источник
4
«[...] не хочу проверять, существует ли файл!»
Стефан
3
Этот тест на наличие каталога, а не на то, что он является действительным путем (где он может существовать или быть создан с учетом соответствующих привилегий)
Martijn
3
@Jason - он не проверяет файл, а только содержащую его папку.
markpsmith 01
8
но действительный путь к каталогу все еще не может существовать.
Стефан
-2
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");

    if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
    {
        return false;
    }

    if (!driveCheck.IsMatch(path.Substring(0, 3)))
    {
        return false;
    }

    var x1 = (path.Substring(3, path.Length - 3));
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":?*";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");

    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
    {
        return false;
    }

    var driveLetterWithColonAndSlash = Path.GetPathRoot(path);

    if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
    {
        return false;
    }

    return true;
}
Гислен Забатио
источник
1
какова цель x1?
JayJay
-3

Просто используйте

if (System.IO.Directory.Exists(path))
{
    ...
}
Махди Астаней
источник
-4

Вы можете попробовать использовать Path.IsPathRooted () в сочетании с Path.GetInvalidFileNameChars (), чтобы убедиться, что путь находится на полпути в порядке.

Ален Милакович
источник