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


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

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


-4

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.