Meilleure façon de vérifier si un chemin est un fichier ou un répertoire?

je traite un TreeView de répertoires et de fichiers. Un utilisateur peut sélectionner un fichier ou un répertoire et de faire quelque chose avec elle. Cela me demande d'avoir une méthode qui effectue différentes actions basées sur la sélection de l'utilisateur.

en ce moment je fais quelque chose comme ça 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 sentir qu'il ya une meilleure façon de le faire! J'espérais trouvez une méthode .NET standard pour gérer cela, mais je n'ai pas été en mesure de le faire. Une telle méthode existe, et si non, quel est le plus simple moyen de déterminer si un chemin est un fichier ou un répertoire?

309
demandé sur DavidRR 2009-09-08 21:24:37

19 réponses

à Partir de Comment savoir si un chemin est le fichier ou le 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 .NET 4.0+

selon les commentaires ci-dessous, si vous êtes sur .NET 4.0 ou plus tard (et la performance maximale n'est pas critique), vous pouvez écrire le code d'une 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");
472
répondu Quinn Wilson 2017-08-28 12:10:16

et si on utilisait ça?

File.Exists();
Directory.Exists();
196
répondu llamaoo7 2009-09-08 17:26:17

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

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
17
répondu Gerard Gilabert Canal 2013-06-21 07:49:04

voici le mien:

    bool IsPathDirectory(string path)
    {
        if (path == null) throw new ArgumentNullException("path");
        path = path.Trim();

        if (Directory.Exists(path)) 
            return true;

        if (File.Exists(path)) 
            return false;

        // neither file nor directory exists. guess intention

        // if has trailing slash then it's a directory
        if (new[] {"\", "/"}.Any(x => path.EndsWith(x)))
            return true; // ends with slash

        // if has extension then its a file; directory otherwise
        return string.IsNullOrWhiteSpace(Path.GetExtension(path));
    }

c'est similaire aux réponses des autres mais pas exactement le même.

7
répondu Ronnie Overby 2014-07-01 14:16:15

comme alternative au répertoire.Exists(), vous pouvez utiliser le Fichier.Méthode GetAttributes () pour obtenir les attributs d'un fichier ou d'un répertoire, pour que vous puissiez créer une méthode helper comme ceci:

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 qui contient des métadonnées supplémentaires pour l'élément. Par exemple, vous pouvez ajouter un objet FileInfo pour les fichiers et un objet DirectoryInfo pour les répertoires. et ensuite tester le type d'item dans la propriété tag pour enregistrer des appels système supplémentaires pour obtenir ces données en cliquant sur l'item.

6
répondu Michael A. McCloskey 2017-12-12 13:02:00

C'est le meilleur que j'ai pu trouver étant donné le comportement des propriétés Exists et Attributes:

using System.IO;

public static class FileSystemInfoExtensions
{
    /// <summary>
    /// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
    /// </summary>
    /// <param name="fileSystemInfo"></param>
    /// <returns></returns>
    public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
    {
        if (fileSystemInfo == null)
        {
            return false;
        }

        if ((int)fileSystemInfo.Attributes != -1)
        {
            // if attributes are initialized check the directory flag
            return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
        }

        // If we get here the file probably doesn't exist yet.  The best we can do is 
        // try to judge intent.  Because directories can have extensions and files
        // can lack them, we can't rely on filename.
        // 
        // We can reasonably assume that if the path doesn't exist yet and 
        // FileSystemInfo is a DirectoryInfo, a directory is intended.  FileInfo can 
        // make a directory, but it would be a bizarre code path.

        return fileSystemInfo is DirectoryInfo;
    }
}

Voici comment il teste:

    [TestMethod]
    public void IsDirectoryTest()
    {
        // non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentFile = @"C:\TotallyFakeFile.exe";

        var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
        Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());

        var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
        Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());

        // non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentDirectory = @"C:\FakeDirectory";

        var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
        Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());

        var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
        Assert.IsFalse(nonExistentFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingDirectory = @"C:\Windows";

        var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryInfo.IsDirectory());

        var existingDirectoryFileInfo = new FileInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingFile = @"C:\Windows\notepad.exe";

        var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
        Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());

        var existingFileFileInfo = new FileInfo(existingFile);
        Assert.IsFalse(existingFileFileInfo.IsDirectory());
    }
5
répondu HAL9000 2013-06-19 18:01:34

l'approche la plus précise sera d'utiliser un code interop du 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 ainsi:

#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);
}
4
répondu Scott Dorman 2013-12-22 00:10:21

voici ce que nous utilisons:

using System;

using System.IO;

namespace crmachine.CommonClasses
{

  public static class CRMPath
  {

    public static bool IsDirectory(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      string reason;
      if (!IsValidPathString(path, out reason))
      {
        throw new ArgumentException(reason);
      }

      if (!(Directory.Exists(path) || File.Exists(path)))
      {
        throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path));
      }

      return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory;
    } 

    public static bool IsValidPathString(string pathStringToTest, out string reasonForError)
    {
      reasonForError = "";
      if (string.IsNullOrWhiteSpace(pathStringToTest))
      {
        reasonForError = "Path is Null or Whitespace.";
        return false;
      }
      if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260
      {
        reasonForError = "Length of path exceeds MAXPATH.";
        return false;
      }
      if (PathContainsInvalidCharacters(pathStringToTest))
      {
        reasonForError = "Path contains invalid path characters.";
        return false;
      }
      if (pathStringToTest == ":")
      {
        reasonForError = "Path consists of only a volume designator.";
        return false;
      }
      if (pathStringToTest[0] == ':')
      {
        reasonForError = "Path begins with a volume designator.";
        return false;
      }

      if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1)
      {
        reasonForError = "Path contains a volume designator that is not part of a drive label.";
        return false;
      }
      return true;
    }

    public static bool PathContainsInvalidCharacters(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < path.Length; i++)
      {
        int n = path[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }


    public static bool FilenameContainsInvalidCharacters(string filename)
    {
      if (filename == null)
      {
        throw new ArgumentNullException("filename");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < filename.Length; i++)
      {
        int n = filename[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n == 0x3a) || // : 
            (n == 0x2a) || // * 
            (n == 0x3f) || // ? 
            (n == 0x5c) || // \ 
            (n == 0x2f) || // /
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }

  }

}
2
répondu PMBottas 2012-07-01 12:31:59

je suis tombé sur ce lorsque faisant face à un problème similaire, sauf que je devais vérifier si un chemin est pour un fichier ou dossier quand ce fichier ou dossier peut ne pas exister réellement . Il y a eu quelques commentaires sur les réponses ci-dessus qui mentionnaient qu'elles ne fonctionneraient pas dans ce scénario. J'ai trouvé une solution (j'utilise VB.NET, mais vous pouvez convertir Si vous avez besoin) qui semble bien fonctionner pour moi:

Dim path As String = "myFakeFolder\ThisDoesNotExist\"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns True

Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns False

espérons que cela puisse être utile à quelqu'un!

2
répondu lhan 2012-10-18 15:51:10

sooo tard dans le jeu je sais, mais j'ai pensé que je partagerais cela de toute façon. Si vous travaillez uniquement avec les chemins en tant que Cordes, comprendre cela est facile comme tarte:

private bool IsFolder(string ThePath)
{
    string BS = Path.DirectorySeparatorChar.ToString();
    return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}

par exemple: ThePath == "C:\SomeFolder\File1.txt" finirait par être ceci:

return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)

autre exemple: ThePath == "C:\SomeFolder\" finirait par être ceci:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

et cela fonctionnerait aussi sans le revers arrière: ThePath == "C:\SomeFolder" est ce:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

Garder à l'esprit que cela ne fonctionne qu'avec les chemins eux-mêmes, et non pas la relation entre le chemin et le "disque physique"... donc il ne peut pas vous dire si le chemin/fichier existe ou quelque chose comme ça, mais c'est sûr qu'il peut vous dire si le chemin est un dossier ou un fichier...

2
répondu MaxOvrdrv 2014-09-17 19:08:14

si vous voulez trouver des répertoires, y compris ceux marqués "hidden" et "system", essayez ceci (requires .NET V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory)) 
1
répondu jamie 2013-04-05 14:40:42

après avoir combiné les suggestions des autres réponses, j'ai réalisé que j'avais trouvé à peu près la même chose que réponse de Ronnie Overby . Voici quelques tests pour souligner quelques choses à penser:

  1. les dossiers peuvent avoir des "extensions": C:\Temp\folder_with.dot
  2. les fichiers ne peuvent pas se terminer par un séparateur de répertoires (slash)
  3. il y a techniquement deux séparateurs de répertoire qui sont plate-forme spécifique - c.-à-d. peut ou ne peut pas être slashes ( Path.DirectorySeparatorChar et Path.AltDirectorySeparatorChar )

Tests (Linqpad)

var paths = new[] {
    // exists
    @"C:\Temp\dir_test\folder_is_a_dir",
    @"C:\Temp\dir_test\is_a_dir_trailing_slash\",
    @"C:\Temp\dir_test\existing_folder_with.ext",
    @"C:\Temp\dir_test\file_thats_not_a_dir",
    @"C:\Temp\dir_test\notadir.txt",
    // doesn't exist
    @"C:\Temp\dir_test\dne_folder_is_a_dir",
    @"C:\Temp\dir_test\dne_folder_trailing_slash\",
    @"C:\Temp\dir_test\non_existing_folder_with.ext",
    @"C:\Temp\dir_test\dne_file_thats_not_a_dir",
    @"C:\Temp\dir_test\dne_notadir.txt",        
};

foreach(var path in paths) {
    IsFolder(path/*, false*/).Dump(path);
}

résultats

C:\Temp\dir_test\folder_is_a_dir
  True 
C:\Temp\dir_test\is_a_dir_trailing_slash\
  True 
C:\Temp\dir_test\existing_folder_with.ext
  True 
C:\Temp\dir_test\file_thats_not_a_dir
  False 
C:\Temp\dir_test\notadir.txt
  False 
C:\Temp\dir_test\dne_folder_is_a_dir
  True 
C:\Temp\dir_test\dne_folder_trailing_slash\
  True 
C:\Temp\dir_test\non_existing_folder_with.ext
  False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
  True 
C:\Temp\dir_test\dne_notadir.txt
  False 

Méthode

/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not); 
/// optionally assume that if it doesn't "look like" a file then it's a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name?  As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
    // /q/better-way-to-check-if-a-path-is-a-file-or-a-directory-2757/"" + Path.DirectorySeparatorChar)
        || path.EndsWith("" + Path.AltDirectorySeparatorChar))
        return true;

    // if we know for sure that it's an actual file...
    if (File.Exists(path))
        return false;

    // if it has an extension it should be a file, so vice versa
    // although technically directories can have extensions...
    if (!Path.HasExtension(path) && assumeDneLookAlike)
        return true;

    // only works for existing files, kinda redundant with `.Exists` above
    //if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...; 

    // no idea -- could return an 'indeterminate' value (nullable bool)
    // or assume that if we don't know then it's not a folder
    return false;
}
1
répondu drzaus 2017-05-23 11:33:26

j'utilise la suite, il teste également l'extension qui signifie qu'il peut être utilisé pour tester si le chemin fourni est un fichier mais un fichier qui n'existe pas.

private static bool isDirectory(string path)
{
    bool result = true;
    System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
    if (fileTest.Exists == true)
    {
        result = false;
    }
    else
    {
        if (fileTest.Extension != "")
        {
            result = false;
        }
    }
    return result;
}
0
répondu Stu1983 2012-02-22 14:05:48
using System;
using System.IO;
namespace FileOrDirectory
{
     class Program
     {
          public static string FileOrDirectory(string path)
          {
               if (File.Exists(path))
                    return "File";
               if (Directory.Exists(path))
                    return "Directory";
               return "Path Not Exists";
          }
          static void Main()
          {
               Console.WriteLine("Enter The Path:");
               string path = Console.ReadLine();
               Console.WriteLine(FileOrDirectory(path));
          }
     }
}
0
répondu Diaa Eddin 2014-05-30 16:42:34

j'avais besoin de cela, les messages ont aidé, cela le fait descendre à une ligne, et si le chemin n'est pas un chemin du tout, il retourne et sort juste de la méthode. Il répond à toutes les préoccupations ci-dessus, n'a pas besoin de la barre oblique.

if (!Directory.Exists(@"C:\folderName")) return;
0
répondu Joe Stellato 2015-03-16 20:24:18

en utilisant la réponse sélectionnée sur ce post, j'ai regardé les commentaires et donner confiance à @ŞafakGür, @Anthony et @Quinn Wilson pour leurs infos qui m'amènent à cette réponse améliorée que j'ai écrite et testée:

    /// <summary>
    /// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist.
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static bool? IsDirFile(this string path)
    {
        bool? result = null;

        if(Directory.Exists(path) || File.Exists(path))
        {
            // get the file attributes for file or directory
            var fileAttr = File.GetAttributes(path);

            if (fileAttr.HasFlag(FileAttributes.Directory))
                result = true;
            else
                result = false;
        }

        return result;
    }
0
répondu Mike Socha III 2015-03-31 19:09:00

peut-être pour UWP C#

public static async Task<IStorageItem> AsIStorageItemAsync(this string iStorageItemPath)
    {
        if (string.IsNullOrEmpty(iStorageItemPath)) return null;
        IStorageItem storageItem = null;
        try
        {
            storageItem = await StorageFolder.GetFolderFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        try
        {
            storageItem = await StorageFile.GetFileFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        return storageItem;
    }
0
répondu Minute V 2018-06-14 12:48:40

ça ne marcherait pas?

var isFile = Regex.IsMatch(path, @"\w{1,}\.\w{1,}$");
-4
répondu 2015-11-20 09:10:23

cela utilise DirectoryInfo pour obtenir l'attribut

Dim newnode As TreeNode
Dim dirs As New DirectoryInfo(node.FullPath)
For Each dir As DirectoryInfo In dirs.GetDirectories()
    If dir.Attributes = FileAttributes.Directory Then

    Else

    End If
Next

cela fonctionnera si vous essayez de passer par DirectoryInfo essayant de créer une vue sur arbre ou lire une vue sur Arbre

-5
répondu DotNet Programmer 2016-06-28 13:36:01