2010-08-19 2 views
72

Можно создать дубликат:
Can you call Directory.GetFiles() with multiple filters?GetFiles с несколькими расширениями

Как фильтровать более чем одно расширение?

Я пробовал:

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

Я думаю, вы имеете в виду «более чем один расширение» ... это не работает с двумя либо –

+0

yeup не работает на два либо – rd42

+0

Кстати, знаете ли вы, что GetFiles не связан с C#, но связан только с .NET? –

ответ

52

Почему бы не создать метод расширения? Это более читаемо.

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: более эффективный вариант:

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

Использование:

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

Это неэффективно. – SLaks

+0

@Slaks: emm..что лучше, если я сначала получу все файлы, а затем фильтрую их с разными расширениями. –

+2

Да. См. Мой ответ. Кроме того, вы должны называть 'SelectMany' вместо' Concat': 'return extensions.SelectMany (dir.GetFiles);' – SLaks

3

Я не уверен, если это возможно. MSDN GetFiles reference говорит шаблон поиска, а не список шаблонов поиска.

Возможно, я склонен отображать каждый список отдельно и «направлять» их в окончательный список.

42

Вы не можете этого сделать, потому что GetFiles принимает только один шаблон поиска. Вместо этого, вы можете позвонить GetFiles, без рисунка, и фильтровать результаты в коде:

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

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

Если вы работаете с .NET 4, вы можете использовать метод EnumerateFiles, чтобы избежать загрузки всех объектов FileInfo в памяти сразу :

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

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

Спасибо, я использовал .NET 4 и получил следующую ошибку. Я новичок в этом, поэтому извинения - это очевидное исправление: Ошибка «bool» не содержит определения для «ToArray», а метод расширения «ToArray», принимающий первый аргумент типа «bool», может быть (вам не хватает директивы использования или ссылки на сборку?) – rd42

+0

Отсутствует закрывающая скобка, я исправил ее –

+0

Точно.EnumerateFiles() лучше работает. –

5

следующая извлекает JPG, файлы TIFF и BMP и дает вам IEnumerable<FileInfo>, по которому вы можете перебирать:

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

Если вам действительно нужен массив, просто нажмите .ToArray() в конце этого.

+3

Это будет очень неэффективно, если в каталоге есть много файлов ... –

1

Я знаю, что есть более элегантный способ сделать это, и я открыт для предложений ... это то, что я сделал:

  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

Вам не нужно создавать отдельный экземпляр DirectoryInfo для каждого типа ... и есть много повторяющегося кода, вы должны реорганизовать это с помощью метод. Во всяком случае, я обновил свой ответ, чтобы исправить ошибку, вы попробовали? –

57

Вы можете получить каждый файл, а затем фильтровать массив:

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

Это будет быть (незначительно) быстрее, чем каждый другой answe здесь.
В .Net 3.5 замените EnumerateFiles на GetFiles (что медленнее).

И использовать его как это:

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

Я использую следующий способ список файлов.

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

Вы можете использовать метод LINQ Union:

dir.GetFiles("*.txt").Union(dir.GetFiles("*.jpg")).ToArray(); 
Смежные вопросы