2010-08-19 22 views
72

Duplicar posibles:
Can you call Directory.GetFiles() with multiple filters?GetFiles con múltiples extensiones

¿Cómo se filtra por más de una extensión?

que he probado:

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

supongo que quiere decir "más de una extensión" ... no funciona con dos o bien –

+0

Yeup no funciona bien para dos – rd42

+0

BTW, ¿sabe usted que GetFiles no está relacionado con C#, sino solo con .NET? –

Respuesta

52

por qué no crear un método de extensión? Eso es más legible.

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: una versión más eficiente:

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)); 
} 

Uso:

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

Esto es ineficiente. – SLaks

+0

@Slaks: emm ... es mejor si primero obtengo todos los archivos y luego los filtro con diferentes extensiones. –

+2

Sí. Ver mi respuesta Además, debe llamar a 'SelectMany' en lugar de' Concat': 'devolver extensiones.SelectMany (dir.GetFiles);' – SLaks

3

No estoy seguro de si eso es posible. MSDN GetFiles reference dice un patrón de búsqueda, no una lista de patrones de búsqueda.

Me inclino a buscar cada lista por separado y "foreach" en una lista final.

42

No puede hacer eso, porque GetFiles solo acepta un patrón de búsqueda único. En su lugar, puede llamar GetFiles sin un patrón, y filtrar los resultados de código:

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

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

Si está trabajando con .NET 4, puede utilizar el método EnumerateFiles para evitar cargar todos los objetos FileInfo en la memoria a la vez :

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

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

Gracias, utilicé el .NET 4 y obtuve el siguiente error. Soy nuevo en esto, así que disculpas es que esto es una solución obvia: Error 'bool' no contiene una definición para 'ToArray' y ningún método de extensión 'ToArray' aceptando un primer argumento de tipo 'bool' podría ser found (¿falta una directiva using o una referencia de ensamblado?) – rd42

+0

Faltaba un paréntesis de cierre, lo arreglé –

+0

Exactly.EnumerateFiles() es mejor en rendimiento. –

5

El siguiente recupera los JPG, TIFF y BMP y le da una IEnumerable<FileInfo> sobre el cual se puede repetir:

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

Si realmente necesita una matriz, simplemente pegue .ToArray() al final de esto.

+3

Eso será muy ineficiente si hay muchos archivos en el directorio ... –

1

Sé que hay una manera más elegante de hacer esto y estoy abierto a sugerencias ... esto es lo que hice:

  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

No necesita crear una instancia separada de DirectoryInfo para cada tipo ... y hay un montón de código repetido, debe refactorizarlo con un método. De todos modos, actualicé mi respuesta para corregir el error, ¿lo intentó? –

57

Usted puede obtener todos los archivos, luego filtrar la matriz:

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)); 
} 

Esta voluntad ser (marginalmente) más rápido que cualquier otro answe aquí.
En .Net 3.5, reemplace EnumerateFiles con GetFiles (que es más lento).

Y utilizar de esta manera:

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

estoy usando siguiente manera para listar los archivos.

'////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

Puede utilizar el método de LINQ Unión:

dir.GetFiles("*.txt").Union(dir.GetFiles("*.jpg")).ToArray(); 
Cuestiones relacionadas