Перевірте, чи дійсний шлях


110

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

Проблема в тому, що я не можу знайти нічого в API .Net. Завдяки безлічі форматів та місць, які підтримує Windows, я б скоріше використовував щось, що відповідає мові MS.

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

  • Відносні шляхи (./)
  • Абсолютні шляхи (c: \ tmp)
  • UNC-Pathes (\ some-pc \ c $)
  • Обмеження NTFS, як повний шлях 1024 символів - Якщо я не помиляюся, перевищення шляху зробить файл недоступним для багатьох внутрішніх функцій Windows. Перейменування його за допомогою Explorer все ще працює
  • Шляхи GUID томів: "\? \ Том {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
Це повертає хибність для @"foo\bar\baz", що є абсолютно вірним відносним шляхом ...
Томас Левеск

5
Томас: Що Ви вказали UriKind? Ви можете використовувати Absolute, Relative або AbsoluteOrRelative.
Dan Gøran Lunde

1
Навіть з UriKind як відносним або абсолютним або відносним він не працював для відносних шляхів, як згадував Томас. Я замість цього скористався відповіддю Патко, і він працює для моїх цілей.
JohnnyM

1
Я виявив, що такий шлях, як \\ computerName \ Dir Name With Spaces \ fileName, видає виняток при використанні IsWellFormedUriString (всупереч моїм початковим очікуванням), оскільки пробіли неправильно закодовані. Я виявив, що я міг просто використовувати конструктор Uri (string) як мою перевірку, таким чином, не потрібно правильно кодувати рядок перед валідацією.
quintessential5

3
Повертає помилку на ідеально хороший шлях до файлу.
Євгеній Петров


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

Наприклад, вони повернуть помилкові:

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." не. '.' є дійсним символом для шляхів / імен файлів, але не в кінці ури.
claudekennilol

0

4
"[...] не хочу перевіряти, чи існує файл!"
Стефан

3
Цей тест для існуючого каталогу, а не для того, щоб він був дійсним шляхом (де він міг би існувати або бути створений з урахуванням належних привілеїв)
Martijn

3
@Jason - Він не перевіряє файл, лише папку, що містить.
стрільщик

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.