Je dois vérifier si le répertoire sur le disque est vide. Cela signifie qu'il ne contient aucun dossier / fichier. Je sais qu'il existe une méthode simple. Nous obtenons un tableau de FileSystemInfo et vérifions si le nombre d'éléments est égal à zéro. Quelque chose comme ca:
public static bool CheckFolderEmpty(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}
var folder = new DirectoryInfo(path);
if (folder.Exists)
{
return folder.GetFileSystemInfos().Length == 0;
}
throw new DirectoryNotFoundException();
}
Cette approche semble correcte. MAIS!! C'est très, très mauvais du point de vue des performances. GetFileSystemInfos () est une méthode très difficile. En fait, il énumère tous les objets du système de fichiers du dossier, récupère toutes leurs propriétés, crée des objets, remplit un tableau typé etc. Et tout cela simplement pour vérifier la longueur. C'est stupide, non?
Je viens de profiler ce code et j'ai déterminé que ~ 250 appels d'une telle méthode sont exécutés en ~ 500 ms. C'est très lent et je pense qu'il est possible de le faire beaucoup plus rapidement.
Aucune suggestion?
Réponses:
Il existe une nouvelle fonctionnalité dans
Directory
etDirectoryInfo
dans .NET 4 qui leur permet de renvoyer unIEnumerable
au lieu d'un tableau et de commencer à renvoyer des résultats avant de lire tout le contenu du répertoire.Directory.EnumerateFileSystemEntries
surcharges de méthodeEDIT: en revoyant cette réponse, je me rends compte que ce code peut être rendu beaucoup plus simple ...
la source
EnumerateFileSystemEntries
, ou utiliser.Any(condition)
(spécifier la condition en tant qu'expression lambda ou en tant que méthode qui prend un chemin comme paramètre).return !items.GetEnumerator().MoveNext();
Voici la solution ultra rapide, que j'ai finalement implémentée. Ici, j'utilise WinAPI et les fonctions FindFirstFile , FindNextFile . Il permet d'éviter l'énumération de tous les éléments dans le dossier et s'arrête juste après la détection du premier objet dans le dossier . Cette approche est ~ 6 (!!) fois plus rapide que celle décrite ci-dessus. 250 appels en 36ms!
J'espère que cela sera utile à quelqu'un à l'avenir.
la source
SetLastError = true
auDllImport
pourFindFirstFile
pour que l'Marshal.GetHRForLastWin32Error()
appel fonctionne correctement, comme décrit dans la section Notes du document MSDN pour GetHRForLastWin32Error () .Vous pouvez essayer
Directory.Exists(path)
etDirectory.GetFiles(path)
- probablement moins de frais généraux (pas d'objets - juste des chaînes, etc.).la source
Ce test rapide est revenu en 2 millisecondes pour le dossier lorsqu'il était vide et lorsqu'il contenait des sous-dossiers et des fichiers (5 dossiers avec 5 fichiers chacun)
la source
J'utilise ceci pour les dossiers et les fichiers (je ne sais pas si c'est optimal)
la source
Si cela ne vous dérange pas de laisser C # pur et de passer des appels WinApi , vous pouvez envisager la fonction PathIsDirectoryEmpty () . Selon le MSDN, la fonction:
Cela semble être une fonction qui fait exactement ce que vous voulez, donc elle est probablement bien optimisée pour cette tâche (bien que je ne l'ai pas testé).
Pour l'appeler depuis C #, le site pinvoke.net devrait vous aider. (Malheureusement, il ne décrit pas encore cette fonction, mais vous devriez être en mesure de trouver des fonctions avec des arguments similaires et de renvoyer le type là-bas et de les utiliser comme base pour votre appel. Si vous regardez à nouveau dans le MSDN, il indique que la DLL à importer est
shlwapi.dll
)la source
Je ne connais pas les statistiques de performances de celui-ci, mais avez-vous essayé d'utiliser la
Directory.GetFiles()
méthode statique?Il renvoie un tableau de chaînes contenant des noms de fichiers (pas FileInfos) et vous pouvez vérifier la longueur du tableau de la même manière que ci-dessus.
la source
Je suis sûr que les autres réponses sont plus rapides, et votre question demandait si un dossier contenait des fichiers ou des dossiers ... mais je pense que la plupart du temps, les gens considéreraient un répertoire vide s'il ne contient pas de fichiers. c'est-à-dire qu'il est toujours "vide" pour moi s'il contient des sous-répertoires vides ... cela peut ne pas convenir à votre usage, mais peut-être pour d'autres!
la source
Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any()
Dans tous les cas, vous devrez aller sur le disque dur pour obtenir ces informations, et cela seul l'emportera sur toute création d'objet et remplissage de tableau.
la source
Je ne connais pas une méthode qui vous dira succinctement si un dossier donné contient d'autres dossiers ou fichiers, cependant, en utilisant:
devrait améliorer les performances car ces deux méthodes ne renverront qu'un tableau de chaînes avec les noms des fichiers / répertoires plutôt que des objets FileSystemInfo entiers.
la source
Facile et simple:
la source
Merci à tous pour les réponses. J'ai essayé d'utiliser Directory.GetFiles () et Directory.GetDirectories () . Bonnes nouvelles! Les performances se sont améliorées ~ deux fois! 229 appels en 221 ms. Mais j'espère aussi qu'il est possible d'éviter l'énumération de tous les éléments du dossier. D'accord, que le travail inutile est toujours en cours d'exécution. Tu ne penses pas?
Après toutes les enquêtes, je suis arrivé à une conclusion, que sous .NET pur, une optimisation supplémentaire est impossible. Je vais jouer avec la fonction FindFirstFile de WinAPI . J'espère que cela aidera.
la source
Vous voudrez peut-être vérifier si des fichiers existent dans les sous-répertoires et ignorer ces sous-répertoires vides; dans ce cas, vous pouvez utiliser la méthode ci-dessous:
la source
Basé dans le code Brad Parks :
la source
Mon code est incroyable, il a juste fallu 00: 00: 00.0007143 moins de milliseconde avec 34 fichiers dans le dossier
la source
Voici quelque chose qui pourrait vous aider à le faire. J'ai réussi à le faire en deux itérations.
la source
Puisque vous allez de toute façon travailler avec un objet DirectoryInfo, j'irais avec une extension
la source
Utilisez ceci. C'est simple.
la source