441 votes

Meilleur moyen de vérifier si un chemin est un fichier ou un répertoire ?

Je suis en train de traiter un TreeView de répertoires et de fichiers. Un utilisateur peut sélectionner soit un fichier, soit un répertoire, puis faire quelque chose avec. Je dois donc disposer d'une méthode qui exécute différentes actions en fonction de la sélection de l'utilisateur.

Pour l'instant, je fais quelque chose comme ceci pour déterminer si le chemin est un fichier ou un répertoire :

bool bIsFile = false;
bool bIsDirectory = false;

try
{
    string[] subfolders = Directory.GetDirectories(strFilePath);

    bIsDirectory = true;
    bIsFile = false;
}
catch(System.IO.IOException)
{
    bIsFolder = false;
    bIsFile = true;
}

Je ne peux m'empêcher de penser qu'il existe une meilleure façon de procéder ! J'espérais trouver une méthode standard .NET pour gérer cela, mais je n'y suis pas parvenu. Une telle méthode existe-t-elle et, si ce n'est pas le cas, quel est le moyen le plus direct de déterminer si un chemin est un fichier ou un répertoire ?

9 votes

Quelqu'un peut-il modifier le titre de la question pour préciser "existant" fichier/répertoire ? Toutes les réponses s'appliquent à un chemin d'accès pour un fichier/répertoire sur le disque.

1 votes

@jberger veuillez vous référer à ma réponse ci-dessous. J'ai trouvé un moyen d'accomplir ceci pour des chemins de fichiers/dossiers qui peuvent ou non exister.

0 votes

670voto

Quinn Wilson Points 2450

Desde Comment savoir si le chemin est un fichier ou un répertoire :

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

//detect whether its a directory or file
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");

Mise à jour pour la version 4.0+ de .NET

D'après les commentaires ci-dessous, si vous utilisez .NET 4.0 ou une version ultérieure (et que les performances maximales ne sont pas critiques), vous pouvez écrire le code de manière plus propre :

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

if (attr.HasFlag(FileAttributes.Directory))
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");

8 votes

+1 C'est la meilleure approche et elle est nettement plus rapide que la solution que j'ai proposée.

2 votes

Et il me semble que c'est la façon "officielle" de le faire. Bravo !

0 votes

Si cela ne fonctionne pas pour les fichiers/dossiers inexistants, ne pourriez-vous pas envelopper le code dans un bloc try/catch et renvoyer false pour les deux (path != file && path != folder) ? Cela m'aide à résoudre mon problème !

279voto

llamaoo7 Points 1330

Et si on utilisait ça ?

File.Exists();
Directory.Exists();

52 votes

Cela présente également l'avantage de ne pas lever une exception en cas de chemin d'accès non valide, contrairement à File.GetAttributes() .

0 votes

J'utilise la bibliothèque Long Path de la BCL bcl.codeplex.com/ dans mon projet, il n'y a donc aucun moyen d'obtenir les attributs du fichier, mais l'appel à Exist est une bonne solution de contournement.

4 votes

@jberger Je m'attendrais à ce que cela ne fonctionne PAS pour les chemins vers des fichiers/dossiers inexistants. File.Exists("c : \\temp\\nonexistant.txt ") devrait retourner false, comme c'est le cas.

22voto

Avec seulement cette ligne vous pouvez obtenir si un chemin est un répertoire ou un fichier :

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)

4 votes

Attention, vous avez besoin d'au moins .NET 4.0 pour cela. De plus, cela explosera si le chemin n'est pas valide.

0 votes

Utilisez un objet FileInfo pour vérifier si le chemin existe : FileInfo pFinfo = new FileInfo(FList[0]) ; if (pFinfo.Exists) { if (File.GetAttributes(FList[0]).HasFlag(FileAttributes.Directory)) {} }. Celle-ci fonctionne pour moi.

0 votes

Si vous avez déjà créé un objet FileInfo et que vous utilisez la propriété Exists de l'instance, pourquoi ne pas accéder à sa propriété Attributes au lieu d'utiliser la méthode statique File.GetAttributes() ?

8voto

Michael McCloskey Points 1765

Comme alternative à Directory.Exists(), vous pouvez utiliser la méthode File.GetAttributes() pour obtenir les attributs d'un fichier ou d'un répertoire, vous pouvez donc créer une méthode d'aide comme celle-ci :

private static bool IsDirectory(string path)
{
    System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
    return (fa & FileAttributes.Directory) != 0;
}

Vous pouvez également envisager d'ajouter un objet à la propriété tag du contrôle TreeView lors du remplissage du contrôle, contenant des métadonnées supplémentaires pour l'élément. Par exemple, vous pourriez ajouter un objet FileInfo pour les fichiers et un objet DirectoryInfo pour les répertoires, puis tester le type d'élément dans la propriété tag afin d'éviter d'effectuer des appels système supplémentaires pour obtenir ces données lorsque vous cliquez sur l'élément.

2 votes

En quoi est-ce différent des autres réponse

7 votes

Plutôt que cet horrible bloc de logique, essayez de isDirectory = (fa & FileAttributes.Directory) != 0);

3voto

Scott Dorman Points 25000

L'approche la plus précise consistera à utiliser le code d'interopérabilité de shlwapi.dll.

[DllImport(SHLWAPI, CharSet = CharSet.Unicode)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);

Vous l'appelleriez alors comme ceci :

#region IsDirectory
/// <summary>
/// Verifies that a path is a valid directory.
/// </summary>
/// <param name="path">The path to verify.</param>
/// <returns><see langword="true"/> if the path is a valid directory; 
/// otherwise, <see langword="false"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <para><paramref name="path"/> is <see langword="null"/>.</para>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para>
/// </exception>
public static bool IsDirectory(string path)
{
    return PathIsDirectory(path);
}

33 votes

Moche. Je déteste l'interop pour faire ces tâches simples. Et ce n'est pas portable. Et c'est moche. Est-ce que j'ai dit que c'était moche ? :)

5 votes

@SoMoS C'est peut-être "moche" à vos yeux, mais c'est quand même l'approche la plus précise. Oui, ce n'est pas une solution portable, mais ce n'était pas ce que la question demandait.

8 votes

Que voulez-vous dire exactement par "précis" ? Elle donne les mêmes résultats que la réponse de Quinn Wilson et nécessite une interopérabilité qui brise la portabilité. Pour moi, elle est aussi précise que les autres solutions et a des effets secondaires que d'autres n'ont pas.

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