web-dev-qa-db-fra.com

Récupération de fichiers à partir d'un répertoire contenant une grande quantité de fichiers

J'ai un répertoire qui contient près de 14 000 000 d'échantillons audio au format * .wav.

Tout stockage simple, pas de sous-répertoires.

Je veux parcourir les fichiers, mais lorsque j'utilise DirectoryInfo.GetFiles() sur ce dossier, l'application entière se bloque pendant quelques minutes!

Cela peut-il être fait d'une autre manière? Peut-être lire 1000, les traiter, puis prendre les 1000 suivants et ainsi de suite?

60
eddyuk

Avez-vous essayé EnumerateFiles méthode de la classe DirectoryInfo?

Comme le dit MSDN

Les méthodes EnumerateFiles et GetFiles diffèrent comme suit: Lorsque vous utilisez EnumerateFiles, vous pouvez commencer à énumérer la collection d'objets FileInfo avant de renvoyer la collection entière; lorsque vous utilisez GetFiles, vous devez attendre que tout le tableau d'objets FileInfo soit renvoyé avant de pouvoir accéder au tableau. Par conséquent, lorsque vous travaillez avec de nombreux fichiers et répertoires, EnumerateFiles peut être plus efficace.

87
Haris Hasan

Dans .NET 4.0, Directory.EnumerateFiles(...) est IEnumerable<string> (Plutôt que string[] De Directory.GetFiles(...)), il peut donc diffuser des entrées plutôt que de les mettre en mémoire tampon toutes; c'est à dire.

foreach(var file in Directory.EnumerateFiles(path)) {
    // ...
}
44
Marc Gravell

vous atteignez la limitation du système de fichiers Windows lui-même. Lorsque le nombre de fichiers dans un répertoire atteint un grand nombre (et 14M est bien au-delà de ce seuil), l'accès au répertoire devient incroyablement lent. Peu importe si vous lisez un fichier à la fois ou 1000, c'est juste un accès au répertoire.

Une façon de résoudre ce problème consiste à créer des sous-répertoires et à séparer vos fichiers en groupes. Si chaque répertoire a 1000-5000 (deviner mais vous pouvez expérimenter avec des nombres réels), vous devriez obtenir des performances décentes en ouvrant/créant/supprimant des fichiers.

C'est pourquoi si vous regardez des applications comme Doxygen, qui crée un fichier pour chaque classe, elles suivent ce schéma et mettent tout dans 2 niveaux de sous-répertoires qui utilisent des noms aléatoires.

17
DXM

Utilisez Win32 Api FindFile fonctions pour le faire sans bloquer l'application.

Vous pouvez également appeler Directory.GetFiles dans un System.Threading.Task (TPL) pour empêcher votre interface utilisateur de geler.

6

Prendre plaisir.

    public List<string> LoadPathToAllFiles(string pathToFolder, int numberOfFilesToReturn)
    {
        var dirInfo = new DirectoryInfo(pathToFolder);
        var firstFiles = dirInfo.EnumerateFiles().Take(numberOfFilesToReturn).ToList();
        return firstFiles.Select(l => l.FullName).ToList();
    }
5
Jaryn

J'ai souvent rencontré ce problème d'accès aux fichiers volumineux dans un seul répertoire. Les sous-répertoires sont une bonne option, mais bientôt même ils n'offrent pas beaucoup d'aide parfois. Ce que je fais maintenant, c'est créer un fichier d'index - un fichier texte avec les noms de tous les fichiers du répertoire (à condition que je crée des fichiers dans ce répertoire). Je lis ensuite le fichier d'index puis ouvre le fichier réel du répertoire pour le traitement

3
Faizul Hussain