Vérifiez si un chemin est valide


110

Je me demande simplement: je cherche un moyen de valider si un chemin donné est valide. (Note: je ne veux pas vérifier si un fichier existe! Je veux seulement prouver la validité du chemin - donc si un fichier pourrait éventuellement exister à l'emplacement) .

Le problème est que je ne trouve rien dans l'API .Net. En raison des nombreux formats et emplacements pris en charge par Windows, je préfère utiliser quelque chose de natif MS.

Étant donné que la fonction doit pouvoir vérifier:

  • Chemins relatifs (./)
  • Chemins absolus (c: \ tmp)
  • Chemins UNC (\ some-pc \ c $)
  • NTFS-Limitations comme le chemin complet 1024 caractères - Si je ne me trompe pas, le dépassement du chemin rendra un fichier inaccessible pour de nombreuses fonctions Windows internes. Le renommer avec Explorer fonctionne toujours
  • Chemins du GUID du volume: "\? \ Volume {GUID} \ somefile.foo

Quelqu'un a-t-il une fonction comme celle-ci?


Réponses:


58

Essayez Uri.IsWellFormedUriString():

  • La chaîne n'est pas correctement échappée.

    http://www.example.com/path???/file name
  • La chaîne est un Uri absolu qui représente un Uri de fichier implicite.

    c:\\directory\filename
  • La chaîne est un URI absolu auquel il manque une barre oblique avant le chemin.

    file://c:/directory/filename
  • La chaîne contient des barres obliques inverses sans échappement même si elles sont traitées comme des barres obliques.

    http:\\host/path/file
  • La chaîne représente un Uri absolu hiérarchique et ne contient pas ": //".

    www.example.com/path/file
  • L'analyseur de l'Uri.Scheme indique que la chaîne d'origine n'était pas bien formée.

    The example depends on the scheme of the URI.

9
Cela renvoie faux pour @"foo\bar\baz", qui est un chemin relatif parfaitement valide ...
Thomas Levesque

5
Thomas: Quel UriKind avez-vous spécifié? Vous pouvez utiliser Absolute, Relative ou AbsoluteOrRelative.
Dan Gøran Lunde

1
Même avec UriKind en tant que Relative ou AbsoluteOrRelative, cela ne fonctionnait pas pour les chemins relatifs comme Thomas l'a mentionné. J'ai fini par utiliser la réponse de Patko à la place et cela fonctionne pour mes besoins.
JohnnyM

1
J'ai trouvé qu'un chemin tel que \\ computerName \ Dir Name With Spaces \ fileName lève une exception lors de l'utilisation d'IsWellFormedUriString (contrairement à mes attentes initiales), car les espaces ne sont pas correctement codés. J'ai trouvé que je pouvais simplement utiliser le constructeur Uri (string) comme validation, évitant ainsi de coder correctement la chaîne avant de valider.
quintessential5

3
Renvoie false sur un chemin de fichier parfaitement fin.
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;
}

7

Je n'ai eu aucun problème avec le code ci-dessous. (Les chemins relatifs doivent commencer par «/» ou «\»).

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

Par exemple, ceux-ci renverraient 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);

Et ceux-ci reviendraient vrai:

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

Vous pouvez essayer ce code:

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

Je ne suis pas sûr que cela couvre tous les cas ...


2

Le plus proche que je suis venu est d'essayer de le créer et de voir s'il réussit.


2

Il y a beaucoup de bonnes solutions ici, mais comme aucune de celles-ci, vérifiez si le chemin est enraciné dans un lecteur existant en voici un autre:

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

Cette solution ne prend pas en compte les chemins relatifs.


1

Récupérez les caractères non valides System.IO.Path.GetInvalidPathChars();et vérifiez si votre chaîne (chemin du répertoire) les contient ou non.


3
Ce n'est pas entièrement valable. "C: \ new.folder" est valide tandis que "C: \ newfolder". n'est pas. '.' est un caractère valide pour un chemin / nom de fichier, mais pas à la fin de l'URI.
claudekennilol

0

4
"[...] je ne veux pas vérifier si un fichier existe!"
Stefan

3
Ce test pour le répertoire existant, pas pour qu'il s'agisse d'un chemin valide (où il peut exister, ou être créé, avec les privilèges appropriés)
Martijn

3
@Jason - Il ne vérifie pas le fichier, seulement le dossier contenant.
markpsmith

8
mais un chemin de répertoire valide ne pouvait toujours pas exister.
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;
}

1
quel est le but de x1?
JayJay


-4

Vous pouvez essayer d'utiliser Path.IsPathRooted () en combinaison avec Path.GetInvalidFileNameChars () pour vous assurer que le chemin est à mi-chemin.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.