J'essaie d'utiliser la Directory.GetFiles()
méthode pour récupérer une liste de fichiers de plusieurs types, tels que mp3
«et jpg
». J'ai essayé les deux solutions suivantes sans succès:
Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
Existe-t-il un moyen de le faire en un seul appel?
c#
filesystems
.net
Jason Z
la source
la source
Réponses:
Pour .NET 4.0 et versions ultérieures,
Pour les versions antérieures de .NET,
modifier: Veuillez lire les commentaires. L'amélioration suggérée par Paul Farry et le problème de mémoire / performance que Christian.K souligne sont tous deux très importants.
la source
s.ToLower().Endswith...
s.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Directory.GetFiles
parDirectory.EnumerateFiles
, msdn.microsoft.com/en-us/library/dd383571.aspx , ce qui évitera les problèmes de mémoire mentionnés par @ Christian.K.Que dis-tu de ça:
Je l'ai trouvé ici (dans les commentaires): http://msdn.microsoft.com/en-us/library/wz42302f.aspx
la source
Parallel.ForEach
pour les mettre en parallèleSi vous avez une grande liste d'extensions à vérifier, vous pouvez utiliser ce qui suit. Je ne voulais pas créer beaucoup d'instructions OR, j'ai donc modifié ce que Lette a écrit.
la source
Path.GetExtension
renvoie '.ext', pas '* .ext' (au moins dans 3.5+)..abc
et que les extensions prises en charge le contiennent.abcd
. Correspondra, mais il ne devrait pas. Pour réparer:supportedExtensions = ".jpg|.abcd|";
avec.Contains(Path.GetExtension(s).ToLower() + "|")
. Autrement dit, incluez votre caractère séparateur dans le test. IMPORTANT: votre caractère séparateur doit également se trouver après la dernière entrée dans les exceptions prises en charge.pour
Vous pourriez:
Directory.EnumerateFiles
pour une amélioration des performances ( Quelle est la différence entre Directory.EnumerateFiles vs Directory.GetFiles? ).EndsWith("aspx", StringComparison.OrdinalIgnoreCase)
plutôt que.ToLower().EndsWith("aspx")
)Mais le véritable avantage de
EnumerateFiles
s'affiche lorsque vous divisez les filtres et fusionnez les résultats:Cela devient un peu plus rapide si vous n'avez pas à les transformer en globes (c'est-à-dire
exts = new[] {"*.mp3", "*.jpg"}
déjà).Évaluation des performances basée sur le test LinqPad suivant (remarque:
Perf
répète simplement le délégué 10000 fois) https://gist.github.com/zaus/7454021(republié et étendu à partir de 'duplicate' car cette question ne demandait spécifiquement aucun LINQ: Multiple file-extensions searchPattern for System.IO.Directory.GetFiles )
la source
.FilterFiles(path, "jpg", "gif")
) est meilleure que des "globes explicites" (ie.FilterFiles(path, "*.jpg", "*.gif")
).Je sais que c'est une vieille question mais LINQ: (.NET40 +)
la source
file.ToLower()
pour faire correspondre facilement les extensions majuscules. Et pourquoi ne pas extraire l'extension en premier, afin que Regex n'ait pas à examiner l'intégralité du chemin:Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
Il existe également une solution de descente qui semble ne pas avoir de mémoire ou de surcharge de performances et être assez élégante:
la source
Une autre façon d'utiliser Linq, mais sans avoir à tout renvoyer et filtrer cela en mémoire.
Il s'agit en fait de 2 appels à
GetFiles()
, mais je pense que cela correspond à l'esprit de la question et les renvoie en un seul énumérable.la source
Nan. Essayez ce qui suit:
Tiré de: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx
la source
Laisser
alors
ou
la source
Je ne peux pas utiliser la
.Where
méthode car je programme en .NET Framework 2.0 (Linq n'est pris en charge que dans .NET Framework 3.5+).Le code ci-dessous n'est pas sensible à la casse (donc
.CaB
ou.cab
sera également répertorié).la source
La fonction suivante recherche sur plusieurs modèles, séparés par des virgules. Vous pouvez également spécifier une exclusion, par exemple: "! Web.config" recherchera tous les fichiers et exclura "web.config". Les motifs peuvent être mélangés.
Usage:
la source
la source
file.Extension.ToLower()
est une mauvaise pratique.String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
dans .NET 2.0 (pas Linq):
Ensuite, utilisez-le:
la source
la source
Je viens de trouver une autre façon de le faire. Toujours pas une opération, mais la jeter pour voir ce que les autres en pensent.
la source
Qu'en est-il de
la source
Faites les extensions que vous voulez une chaîne, c'est-à-dire ".mp3.jpg.wma.wmf", puis vérifiez si chaque fichier contient l'extension souhaitée. Cela fonctionne avec .net 2.0 car il n'utilise pas LINQ.
L'avantage de cette approche est que vous pouvez ajouter ou supprimer des extensions sans modifier le code, c'est-à-dire pour ajouter des images png, il suffit d'écrire myExtensions = ". Jpg.mp3.png".
la source
s
la source
Non ... Je crois que vous devez faire autant d'appels que les types de fichiers que vous souhaitez.
Je créerais moi-même une fonction en prenant un tableau sur les chaînes avec les extensions dont j'ai besoin, puis j'itérerais sur ce tableau en faisant tous les appels nécessaires. Cette fonction retournerait une liste générique des fichiers correspondant aux extensions que j'avais envoyées.
J'espère que cela aide.
la source
J'ai eu le même problème et je n'ai pas trouvé la bonne solution, j'ai donc écrit une fonction appelée GetFiles:
Cette fonction n'appellera
Directory.Getfiles()
qu'une seule fois.Par exemple, appelez la fonction comme ceci:
EDIT: Pour obtenir un fichier avec plusieurs extensions, utilisez celui-ci:
Par exemple, appelez la fonction comme ceci:
la source
Je me demande pourquoi il y a tant de "solutions" affichées?
Si ma compréhension débutante sur le fonctionnement de GetFiles est correcte, il n'y a que deux options et l'une des solutions ci-dessus peut être réduite à celles-ci:
GetFiles, puis filtre: rapide, mais un tueur de mémoire dû au stockage de la surcharge jusqu'à ce que les filtres soient appliqués
Filtrer pendant que GetFiles: Plus les filtres sont définis, plus lent, mais la faible utilisation de la mémoire car aucune surcharge n'est stockée.
Ceci est expliqué dans l'un des articles ci-dessus avec un point de repère impressionnant: chaque option de filtre provoque une opération GetFile distincte, de sorte que la même partie du disque dur est lue plusieurs fois.
À mon avis, l'option 1) est meilleure, mais l'utilisation de SearchOption.AllDirectories sur des dossiers comme C: \ utiliserait d'énormes quantités de mémoire.
À cet effet, je ferais simplement une sous-méthode récursive qui passe par tous les sous-dossiers en utilisant l'option 1)
Cela ne devrait provoquer qu'une seule opération GetFiles sur chaque dossier et donc rapide (Option 1), mais n'utilisez qu'une petite quantité de mémoire car les filtres sont appliqués après la lecture de chaque sous-dossier -> la surcharge est supprimée après chaque sous-dossier.
S'il vous plait corrigez moi si je me trompe. Je suis comme je l'ai dit assez nouveau dans la programmation, mais je veux acquérir une meilleure compréhension des choses pour finalement devenir bon dans ce domaine :)
la source
Si vous utilisez VB.NET (ou avez importé la dépendance dans votre projet C #), il existe en fait une méthode pratique qui permet de filtrer pour plusieurs extensions:
Dans VB.NET, cela est accessible via le My-namespace:
Malheureusement, ces méthodes pratiques ne prennent pas en charge une variante évaluée paresseusement comme le
Directory.EnumerateFiles()
fait.la source
je ne sais pas quelle solution est la meilleure, mais j'utilise ceci:
la source
Voici un moyen simple et élégant d'obtenir des fichiers filtrés
la source
Ou vous pouvez simplement convertir la chaîne d'extensions en chaîne ^
la source
L'utilisation du modèle de recherche GetFiles pour filtrer l'extension n'est pas sûre !! Par exemple, vous avez deux fichiers Test1.xls et Test2.xlsx et vous souhaitez filtrer le fichier xls en utilisant le modèle de recherche * .xls, mais GetFiles renvoie à la fois Test1.xls et Test2.xlsx Je n'étais pas au courant de cela et j'ai eu une erreur de production environnement lorsque certains fichiers temporaires ont été soudainement traités comme de bons fichiers. Le modèle de recherche était * .txt et les fichiers temporaires étaient nommés * .txt20181028_100753898 Donc, le modèle de recherche ne peut pas être approuvé, vous devez également ajouter une vérification supplémentaire sur les noms de fichiers.
la source