104 votes

Vérifiez si une chaîne est un chemin de répertoire valide pour Windows (dossier)

Je suis en train de déterminer si une chaîne saisie par un utilisateur est valide pour représenter un chemin d'accès à un dossier. Par valide, je veux dire formaté correctement.

Dans mon application, le dossier représente une destination d'installation. À condition que le chemin d'accès au dossier soit valide, je veux déterminer si le dossier existe, et le créer s'il n'existe pas.

J'utilise actuellement IO.Directory.Exists( String path ). Je trouve que cela fonctionne bien sauf lorsque l'utilisateur ne formate pas correctement la chaîne. Dans ce cas, cette méthode retournera false ce qui indique que le dossier n'existe pas. Mais c'est un problème parce que je ne pourrai pas créer le dossier par la suite.

D'après mes recherches sur Internet, j'ai trouvé une suggestion d'utiliser une expression régulière pour vérifier si le format est correct. Je n'ai aucune expérience avec les expressions régulières, et je me demande si c'est une approche viable. Voici ce que j'ai trouvé:

Regex r = new Regex( @"^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$" );
return r.IsMatch( path );

Est-ce qu'un test d'expression régulière en combinaison avec Directory.Exists() me donnerait une méthode assez bonne pour vérifier si le chemin est valide et s'il existe? Je sais que cela variera en fonction du système d'exploitation et d'autres facteurs, mais le programme est destiné uniquement aux utilisateurs de Windows.

138voto

SLaks Points 391154

Appelez Path.GetFullPath; il lancera des exceptions si le chemin est invalide.

Pour interdire les chemins relatifs (comme Word), appelez Path.IsPathRooted.

17voto

Je suis en désaccord avec SLaks. Cette solution n'a pas fonctionné pour moi. L'exception ne s'est pas produite comme prévu. Mais ce code a fonctionné pour moi :

if(System.IO.Directory.Exists(path))
{
    ...
}

16voto

Lusion Nectar Points 124

Path.GetFullPath donne uniquement les exceptions suivantes

ArgumentException le chemin est une chaîne de longueur nulle, ne contient que des espaces blancs ou contient un ou plusieurs des caractères non valides définis dans GetInvalidPathChars. -ou- Le système n'a pas pu récupérer le chemin absolu.

SecurityException L'appelant n'a pas les autorisations requises.

ArgumentNullException le chemin est nul.

NotSupportedException le chemin contient deux points (":") qui ne font pas partie d'un identifiant de volume (par exemple, "c:\").

PathTooLongException Le chemin spécifié, le nom du fichier, ou les deux dépassent la longueur maximale définie par le système. Par exemple, sur les plates-formes basées sur Windows, les chemins doivent être inférieurs à 248 caractères, et les noms de fichiers doivent être inférieurs à 260 caractères.

Une façon alternative est d'utiliser le suivant :

/// 
/// Valider le chemin. Si le chemin est relatif, ajoutez par défaut le chemin au répertoire du projet.
/// 
/// Chemin à valider
/// Chemin relatif
/// Si vous voulez vérifier le chemin du fichier
/// 
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "")
{
    // Vérifiez s'il contient des caractères non valides.
    if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
    {
        try
        {
            // Si le chemin est relatif, prendre %IGXLROOT% comme répertoire de base
            if (!Path.IsPathRooted(path))
            {
                if (string.IsNullOrEmpty(RelativePath))
                {
                    // Exceptions gérées par Path.GetFullPath
                    // ArgumentException le chemin est une chaîne de longueur nulle, ne contient que des espaces blancs 
                    // ou contient un ou plusieurs des caractères non valides définis dans GetInvalidPathChars. -ou- Le système n'a pas pu récupérer le chemin absolu.
                    // 
                    // SecurityException L'appelant n'a pas les autorisations requises.
                    // 
                    // ArgumentNullException le chemin est nul.
                    // 
                    // NotSupportedException le chemin contient deux points (":") qui ne font pas partie d'un identifiant de volume (par exemple, "c:\").
                    // PathTooLongException Le chemin spécifié, le nom du fichier, ou les deux dépassent la longueur maximale définie par le système. Par exemple, sur les plates-formes basées sur Windows, les chemins doivent être inférieurs à 248 caractères, et les noms de fichiers doivent être inférieurs à 260 caractères.

                    // RelativePath n'est pas passé donc nous prendrons le chemin du projet
                    path = Path.GetFullPath(RelativePath);

                }
                else
                {
                    // Assurez-vous que le chemin est relatif au RelativePath et non à notre répertoire de projet
                    path = Path.Combine(RelativePath, path);
                }
            }

            // Exceptions du constructeur FileInfo :
            // System.ArgumentNullException :
            //     fileName est nul.
            //
            // System.Security.SecurityException:
            //     L'appelant n'a pas les autorisations requises.
            //
            // System.ArgumentException:
            //     Le nom de fichier est vide, contient uniquement des espaces blancs ou contient des caractères non valides.
            //
            // System.IO.PathTooLongException:
            //     Le chemin spécifié, le nom du fichier, ou les deux dépassent la longueur maximale définie par le système. Par exemple, sur les plateformes basées sur Windows, les chemins doivent être inférieurs à
            //     248 caractères, et les noms de fichiers doivent être inférieurs à
            //     260 caractères.
            //
            // System.NotSupportedException:
            //     fileName contient un deux points (:) au milieu de la chaîne.
            FileInfo fileInfo = new FileInfo(path);

            // Exceptions en utilisant FileInfo.Length :
            // System.IO.IOException:
            //     System.IO.FileSystemInfo.Refresh() ne peut pas mettre à jour l'état du fichier ou du répertoire.
            //
            // System.IO.FileNotFoundException:
            //     Le fichier n'existe pas.-ou- La propriété Longueur est appelée pour un répertoire.
            bool throwEx = fileInfo.Length == -1;

            // Exceptions en utilisant FileInfo.IsReadOnly :
            // System.UnauthorizedAccessException:
            //     L'accès à fileName est refusé.
            //     Le fichier décrit par l'objet FileInfo actuel est en lecture seule.-ou-
            //     Cette opération n'est pas prise en charge sur la plate-forme actuelle.-ou- L'appelant n'a pas
            //     les autorisations requises.
            throwEx = fileInfo.IsReadOnly;

            if (!string.IsNullOrEmpty(Extension))
            {
                // Valider l'extension du fichier.
                if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase))
                {
                    // Retranchez le chemin de la bibliothèque
                    path = path.Trim();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return true;

            }
        }
        catch (ArgumentNullException)
        {
            //   System.ArgumentNullException:
            //     fileName est nul.
        }
        catch (System.Security.SecurityException)
        {
            //   System.Security.SecurityException:
            //     L'appelant n'a pas les autorisations requises.
        }
        catch (ArgumentException)
        {
            //   System.ArgumentException:
            //     Le nom de fichier est vide, contient uniquement des espaces blancs ou contient des caractères non valides.
        }
        catch (UnauthorizedAccessException)
        {
            //   System.UnauthorizedAccessException:
            //     L'accès à fileName est refusé.
        }
        catch (PathTooLongException)
        {
            //   System.IO.PathTooLongException:
            //     Le chemin spécifié, le nom du fichier ou les deux dépassent la longueur maximale définie
            //     par le système. Par exemple, sur les plates-formes basées sur Windows, les chemins doivent être inférieurs à
            //     248 caractères, et les noms de fichiers doivent être inférieurs à 260 caractères.
        }
        catch (NotSupportedException)
        {
            //   System.NotSupportedException:
            //     fileName contient un deux points (:) au milieu de la chaîne.
        }
        catch (FileNotFoundException)
        {
            // System.FileNotFoundException
            // L'exception qui est levée lorsqu'une tentative d'accès à un fichier qui n'existe pas
            // échoue sur disque.
        }
        catch (IOException)
        {
            //   System.IO.IOException:
            //     Une erreur d'E/S s'est produite lors de l'ouverture du fichier.
        }
        catch (Exception)
        {
            // Exception inconnue. Peut être due à un mauvais cas ou à des vérifications nulles.
        }
    }
    else
    {
        // Le chemin contient des caractères non valides
    }
    return false;
}

12voto

DavidRR Points 2211

Voici une solution qui exploite l'utilisation de Path.GetFullPath comme recommandé dans la réponse de @SLaks.

Dans le code que j'inclus ici, notez que IsValidPath(string path) est conçu de telle sorte que l'appelant n'ait pas à se soucier de la gestion des exceptions.

Vous constaterez peut-être également que la méthode qu'il appelle, TryGetFullPath(...), a également un intérêt en soi lorsque vous souhaitez essayer en toute sécurité d'obtenir un chemin absolu.

/// 
/// Obtient une valeur indiquant si 
/// est un chemin valide.
/// 
/// Renvoie true si  est un
/// chemin valide; false sinon. Renvoie également false si
/// l'appelant n'a pas les autorisations requises pour accéder à
/// .
/// 
/// 
/// 
public static bool IsValidPath(string path)
{
    string result;
    return TryGetFullPath(path, out result);
}

/// 
/// Renvoie le chemin absolu pour la chaîne de chemin spécifiée. Une valeur
/// de retour indique si la conversion a réussi.
/// 
/// Le fichier ou le répertoire pour lequel obtenir des informations de chemin absolu.
/// 
/// Lorsque cette méthode se termine, contient la représentation du chemin absolu
/// de , si la conversion a réussi, ou  si la conversion a 
/// échoué. La conversion échoue si  est nul ou
/// , ou n'est pas au format correct. Ce
/// paramètre est passé non initialisé; toute valeur initialement fournie
/// dans  sera écrasée.
/// 
/// true si  a été converti
/// en un chemin absolu avec succès; sinon, faux.
/// 
/// 
/// 
public static bool TryGetFullPath(string path, out string result)
{
    result = String.Empty;
    if (String.IsNullOrWhiteSpace(path)) { return false; }
    bool status = false;

    try
    {
        result = Path.GetFullPath(path);
        status = true;
    }
    catch (ArgumentException) { }
    catch (SecurityException) { }
    catch (NotSupportedException) { }
    catch (PathTooLongException) { }

    return status;
}

7voto

Alex Jolig Points 466
    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;
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X