Sprawdź, czy ścieżka jest prawidłowa

110

Zastanawiam się tylko: szukam sposobu na sprawdzenie, czy podana ścieżka jest prawidłowa. (Uwaga: nie chcę sprawdzać, czy plik istnieje! Chcę tylko udowodnić poprawność ścieżki - więc jeśli plik może istnieć w tej lokalizacji) .

Problem w tym, że nie mogę znaleźć niczego w .Net API. Ze względu na wiele formatów i lokalizacji obsługiwanych przez system Windows, wolałbym raczej użyć czegoś natywnego dla MS.

Ponieważ funkcja powinna być w stanie sprawdzić:

  • Względne ścieżki (./)
  • Bezwzględne ścieżki (c: \ tmp)
  • UNC-Pathes (\ some-pc \ c $)
  • Ograniczenia NTFS, takie jak pełna ścieżka 1024 znaków - Jeśli się nie mylę, przekroczenie ścieżki spowoduje, że plik będzie niedostępny dla wielu wewnętrznych funkcji systemu Windows. Zmiana nazwy na Explorer nadal działa
  • Ścieżki GUID woluminu: "\? \ Volume {GUID} \ somefile.foo

Czy ktoś ma taką funkcję?

Tobias Boschek
źródło

Odpowiedzi:

58

Spróbuj Uri.IsWellFormedUriString():

  • Ciąg nie ma poprawnej zmiany znaczenia.

    http://www.example.com/path???/file name
  • Ciąg jest absolutnym Uri, który reprezentuje niejawny plik Uri.

    c:\\directory\filename
  • Ciąg jest bezwzględnym identyfikatorem URI, w którym brakuje ukośnika przed ścieżką.

    file://c:/directory/filename
  • Ciąg zawiera odwrotne ukośniki bez zmiany znaczenia, nawet jeśli są one traktowane jako ukośniki w przód.

    http:\\host/path/file
  • Ciąg reprezentuje hierarchiczny bezwzględny Uri i nie zawiera „: //”.

    www.example.com/path/file
  • Parser Uri.Scheme wskazuje, że oryginalny ciąg nie został poprawnie sformułowany.

    The example depends on the scheme of the URI.
abatishchev
źródło
9
To zwraca fałsz dla @"foo\bar\baz", co jest całkowicie poprawną ścieżką względną ...
Thomas Levesque,
5
Thomas: Jaki UriKind określiłeś? Możesz użyć opcji Absolute, Relative lub AbsoluteOrRelative.
Dan Gøran Lunde
1
Nawet z UriKind as Relative lub AbsoluteOrRelative nie działało to dla ścieżek względnych, jak wspomniał Thomas. Skończyło się na tym, że zamiast tego użyłem odpowiedzi Patko i działa to do moich celów.
JohnnyM,
1
Zauważyłem, że ścieżka, taka jak \\ nazwa_komputera \ nazwa katalogu ze spacjami \ nazwa_pliku, zgłasza wyjątek podczas używania IsWellFormedUriString (w przeciwieństwie do moich początkowych oczekiwań), ponieważ spacje nie są poprawnie zakodowane. Odkryłem, że mogę po prostu użyć konstruktora Uri (string) jako mojej walidacji, dzięki czemu nie muszę poprawnie kodować ciągu przed walidacją.
kwintesencja 5
3
Zwraca fałsz w przypadku idealnie dobrej ścieżki do pliku.
Evgeni Petrov
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;
}
Alex Jolig
źródło
7

Nie miałem żadnych problemów z poniższym kodem. (Względne ścieżki muszą zaczynać się od „/” lub „\”).

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

Na przykład te zwróciłyby fałsz:

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

A te zwrócą prawdę:

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);
Poszukiwacz Dao
źródło
3

Możesz wypróbować ten kod:

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

Nie jestem pewien, czy obejmuje wszystkie przypadki ...

Nimrod
źródło
2

Najbliżej mi było próbować go stworzyć i zobaczyć, czy się powiedzie.

Martijn
źródło
2

Jest tutaj wiele dobrych rozwiązań, ale ponieważ żadne z nich nie jest sprawdzane, czy ścieżka jest zakorzeniona w istniejącym dysku, oto kolejny:

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

To rozwiązanie nie uwzględnia ścieżek względnych.

Gark Garcia
źródło
1

Pobierz nieprawidłowe znaki z System.IO.Path.GetInvalidPathChars();i sprawdź, czy twój ciąg (ścieżka do katalogu) je zawiera, czy nie.

Umesh CHILAKA
źródło
3
To nie jest całkowicie poprawne. „C: \ nowy.folder” jest poprawny, a „C: \ nowyfolder”. nie jest. '.' jest poprawnym znakiem dla ścieżek / nazw plików, ale nie na końcu uri.
claudekennilol
0

Katalog istnieje?

markpsmith
źródło
4
„[...] nie chcę sprawdzać, czy plik istnieje!”
Stefan
3
Ten test na istniejący katalog, a nie na to, że jest to poprawna ścieżka (gdzie może istnieć lub zostać utworzona z odpowiednimi uprawnieniami)
Martijn
3
@Jason - nie sprawdza pliku, tylko folder zawierający.
markpsmith
8
ale prawidłowa ścieżka katalogu nadal nie może istnieć.
Stefan
-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;
}
Ghislain Zabatio
źródło
1
jaki jest cel x1?
JayJay,
-3

Po prostu użyj

if (System.IO.Directory.Exists(path))
{
    ...
}
Mahdi Astanei
źródło
-4

Możesz spróbować użyć Path.IsPathRooted () w połączeniu z Path.GetInvalidFileNameChars (), aby upewnić się, że ścieżka jest w połowie w porządku.

Alen Milakovic
źródło