2010-08-19 3 views
72

Possible en double:
Can you call Directory.GetFiles() with multiple filters?GetFiles avec plusieurs extensions

Comment filtrer sur plus d'une extension?

J'ai essayé:

FileInfo[] Files = dinfo.GetFiles("*.jpg;*.tiff;*.bmp"); 
FileInfo[] Files = dinfo.GetFiles("*.jpg,*.tiff,*.bmp"); 
+0

Je suppose que vous voulez dire « plus d'une extension » ... il ne fonctionne pas avec deux soit –

+0

yeup ne fonctionne pas pour deux soit – rd42

+0

BTW, savez-vous que GetFiles n'est pas lié à C#, mais seulement lié à .NET? –

Répondre

52

Pourquoi ne pas créer une méthode d'extension? C'est plus lisible.

public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions) 
{ 
    if (extensions == null) 
     throw new ArgumentNullException("extensions"); 
    IEnumerable<FileInfo> files = Enumerable.Empty<FileInfo>(); 
    foreach(string ext in extensions) 
    { 
     files = files.Concat(dir.GetFiles(ext)); 
    } 
    return files; 
} 

EDIT: une version plus efficace:

public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions) 
{ 
    if (extensions == null) 
     throw new ArgumentNullException("extensions"); 
    IEnumerable<FileInfo> files = dir.EnumerateFiles(); 
    return files.Where(f => extensions.Contains(f.Extension)); 
} 

Utilisation:

dInfo.GetFilesByExtensions(".jpg",".exe",".gif"); 
+7

Ceci est inefficace. – SLaks

+0

@Slaks: emm..it est préférable si je reçois tous les fichiers d'abord, puis filtre avec des extensions différentes. –

+2

Oui. Vois ma réponse. En outre, vous devez appeler 'SelectMany' au lieu de' Concat': 'return extensions.SelectMany (dir.GetFiles);' – SLaks

3

Je ne sais pas si cela est possible. Le GetFiles MSDN reference indique un modèle de recherche, pas une liste de modèles de recherche.

Je pourrais être enclin à aller chercher chaque liste séparément et à les "foreach" dans une liste finale.

42

Vous ne pouvez pas faire cela, car GetFiles n'accepte qu'un seul motif de recherche. Au lieu de cela, vous pouvez appeler GetFiles sans motif, et filtrer les résultats dans le code:

string[] extensions = new[] { ".jpg", ".tiff", ".bmp" }; 

FileInfo[] files = 
    dinfo.GetFiles() 
     .Where(f => extensions.Contains(f.Extension.ToLower())) 
     .ToArray(); 

Si vous travaillez avec .NET 4, vous pouvez utiliser la méthode EnumerateFiles pour éviter de charger tous les objets FileInfo en mémoire à la fois :

string[] extensions = new[] { ".jpg", ".tiff", ".bmp" }; 

FileInfo[] files = 
    dinfo.EnumerateFiles() 
     .Where(f => extensions.Contains(f.Extension.ToLower())) 
     .ToArray(); 
+0

Merci, j'ai utilisé le .NET 4 et j'ai eu l'erreur suivante. Je suis nouveau à ceci, donc les excuses est ceci est une correction évidente: Erreur 'bool' ne contient pas une définition pour 'ToArray' et aucune méthode d'extension 'ToArray' acceptant un premier argument de type 'bool' pourrait être trouvé (manque-t-il une directive using ou une référence d'assembly?) – rd42

+0

Une parenthèse fermante était manquante, je l'ai fixée –

+0

Exactly.EnumerateFiles() est meilleur à la représentation. –

5

qui suit permet de récupérer les fichiers JPG, tIFF et BMP et vous donne un IEnumerable<FileInfo> sur lequel vous pouvez itérer:

var files = dinfo.GetFiles("*.jpg") 
    .Concat(dinfo.GetFiles("*.tiff")) 
    .Concat(dinfo.GetFiles("*.bmp")); 

Si vous avez vraiment besoin d'un tableau, collez simplement .ToArray() à la fin de ceci.

+3

Ce sera très inefficace s'il y a beaucoup de fichiers dans le répertoire ... –

1

Je sais qu'il ya une façon plus élégante de le faire et je suis ouvert aux suggestions ... ce que je l'ai fait:

  try 
      { 


      // Set directory for list to be made of 
       DirectoryInfo jpegInfo = new DirectoryInfo(destinationFolder); 
       DirectoryInfo jpgInfo = new DirectoryInfo(destinationFolder); 
       DirectoryInfo gifInfo = new DirectoryInfo(destinationFolder); 
       DirectoryInfo tiffInfo = new DirectoryInfo(destinationFolder); 
       DirectoryInfo bmpInfo = new DirectoryInfo(destinationFolder); 

       // Set file type 
       FileInfo[] Jpegs = jpegInfo.GetFiles("*.jpeg"); 
       FileInfo[] Jpgs = jpegInfo.GetFiles("*.jpg"); 
       FileInfo[] Gifs = gifInfo.GetFiles("*.gif"); 
       FileInfo[] Tiffs = gifInfo.GetFiles("*.tiff"); 
       FileInfo[] Bmps = gifInfo.GetFiles("*.bmp"); 

     // listBox1.Items.Add(@""); // Hack for the first list item no preview problem 
     // Iterate through each file, displaying only the name inside the listbox... 
     foreach (FileInfo file in Jpegs) 
     { 
       listBox1.Items.Add(file.Name); 
       Photo curPhoto = new Photo(); 
       curPhoto.PhotoLocation = file.FullName; 
       metaData.AddPhoto(curPhoto); 
      } 

      foreach (FileInfo file in Jpgs) 
      { 
       listBox1.Items.Add(file.Name); 
       Photo curPhoto = new Photo(); 
       curPhoto.PhotoLocation = file.FullName; 
       metaData.AddPhoto(curPhoto); 
      } 
      foreach (FileInfo file in Gifs) 
      { 
       listBox1.Items.Add(file.Name); 
       Photo curPhoto = new Photo(); 
       curPhoto.PhotoLocation = file.FullName; 
       metaData.AddPhoto(curPhoto); 
      } 
      foreach (FileInfo file in Tiffs) 
      { 
       listBox1.Items.Add(file.Name); 
       Photo curPhoto = new Photo(); 
       curPhoto.PhotoLocation = file.FullName; 
       metaData.AddPhoto(curPhoto); 
      } 
      foreach (FileInfo file in Bmps) 
      { 
       listBox1.Items.Add(file.Name); 
       Photo curPhoto = new Photo(); 
       curPhoto.PhotoLocation = file.FullName; 
       metaData.AddPhoto(curPhoto); 
      } 
+0

Vous n'avez pas besoin de créer une instance séparée de DirectoryInfo pour chaque type ... et il y a beaucoup de code répété, vous devriez refactoriser cela avec une méthode. Quoi qu'il en soit, j'ai mis à jour ma réponse pour corriger l'erreur, l'avez-vous essayé? –

57

Vous pouvez obtenir tous les fichiers, puis filtrer le tableau:

public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dirInfo, params string[] extensions) 
{ 
    var allowedExtensions = new HashSet<string>(extensions, StringComparer.OrdinalIgnoreCase); 

    return dirInfo.EnumerateFiles() 
        .Where(f => allowedExtensions.Contains(f.Extension)); 
} 

Cette volonté être (marginalement) plus rapide que tous les autres r ici.
Dans .Net 3.5, remplacez EnumerateFiles par GetFiles (ce qui est plus lent).

Et l'utiliser comme ceci:

var files = new DirectoryInfo(...).GetFilesByExtensions(".jpg", ".mov", ".gif", ".mp4"); 
-3

J'utilise comme suit pour lister les fichiers.

'////cblSourceFiles is CHECK BOX LIST CONTROL 

<_asp:CheckBoxList ID="cblSourceFiles" runat="server" DataTextField="Name" DataValueField="Name" /> 



     cblSourceFiles.DataSource = (New IO.DirectoryInfo(Path)).EnumerateFiles().Where(AddressOf ValidExtensions) 
     cblSourceFiles.DataBind() 


    Private Function ValidExtensions(ByVal pFi As System.IO.FileInfo, ByVal pSt As Integer) As Boolean 
     Dim mRet As Boolean = False 
     For Each mExt As String In ".jpg,.png".Split(",") '//// WebConfig.AllowedFiletypes 
      If pFi.Extension.ToLower = mExt.ToLower Then 
       mRet = True 
       Exit For 
      End If 
     Next 
     Return mRet 
    End Function 
11

Vous pouvez utiliser la méthode LINQ Union:

dir.GetFiles("*.txt").Union(dir.GetFiles("*.jpg")).ToArray(); 
Questions connexes