2010-08-19 11 views
72

thể trùng lặp:
Can you call Directory.GetFiles() with multiple filters?GetFiles với nhiều phần mở rộng

Làm thế nào để bạn lọc trên nhiều hơn một phần mở rộng?

Tôi đã thử:

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

Tôi đoán bạn có nghĩa là "nhiều hơn một phần mở rộng" ... nó không hoạt động với hai hoặc –

+0

yeup không làm việc cho hai hoặc – rd42

+0

BTW, bạn có biết rằng GetFiles không liên quan đến C#, nhưng chỉ liên quan đến .NET? –

Trả lời

52

Tại sao không tạo ra một phương pháp mở rộng? Đó là dễ đọc hơn.

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: một phiên bản hiệu quả hơn:

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

Cách sử dụng:

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

Điều này không hiệu quả. – SLaks

+0

@Slaks: emm..it tốt hơn nếu tôi nhận được tất cả các tệp trước và sau đó lọc nó với các phần mở rộng khác nhau. –

+2

Có. Xem câu trả lời của tôi. Ngoài ra, bạn nên gọi 'SelectMany' thay vì' Concat': 'return extensions.SelectMany (dir.GetFiles);' – SLaks

3

Tôi không chắc chắn nếu điều đó là có thể. MSDN GetFiles reference nói mẫu tìm kiếm, không phải danh sách mẫu tìm kiếm.

Tôi có thể nghiêng để tìm nạp từng danh sách riêng biệt và "foreach" chúng vào danh sách cuối cùng.

42

Bạn không thể làm điều đó, bởi vì GetFiles chỉ chấp nhận một mẫu tìm kiếm duy nhất. Thay vào đó, bạn có thể gọi GetFiles không có hoa văn, và lọc các kết quả trong mã:

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

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

Nếu bạn đang làm việc với .NET 4, bạn có thể sử dụng phương pháp EnumerateFiles để tránh tải tất cả các đối tượng FileInfo trong bộ nhớ cùng một lúc :

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

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

Cảm ơn, tôi đã sử dụng .NET 4 và gặp lỗi sau. Tôi mới làm điều này, vì vậy xin lỗi đây là một sửa chữa rõ ràng: Lỗi \t 4 'bool' không chứa định nghĩa cho 'ToArray' và không có phương pháp mở rộng 'ToArray' chấp nhận đối số đầu tiên của loại 'bool' có thể là tìm thấy (bạn đang thiếu một chỉ thị sử dụng hoặc một tham chiếu lắp ráp?) – rd42

+0

Một khung đóng bị thiếu, tôi đã sửa nó –

+0

Chính xác.EnumerateFiles() có hiệu suất tốt hơn. –

5

sau đây lấy jpg, tiff và bmp tập tin và cung cấp cho bạn một IEnumerable<FileInfo> qua đó bạn có thể lặp:

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

Nếu bạn thực sự cần một mảng, chỉ cần gắn .ToArray() vào cuối phần này.

+3

Điều đó sẽ rất kém hiệu quả nếu có nhiều tệp trong thư mục ... –

1

Tôi biết có một cách thanh lịch hơn để làm điều này và tôi là mở để gợi ý ... Đây là những gì tôi đã làm:

  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

Bạn không cần phải tạo một cá thể riêng biệt của DirectoryInfo cho từng loại ... và có rất nhiều mã lặp lại, bạn nên cấu trúc lại bằng một phương pháp. Dù sao, tôi đã cập nhật câu trả lời của mình để sửa lỗi, bạn đã thử chưa? –

57

Bạn có thể nhận được tất cả các file, sau đó lọc các mảng:

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

chí này được (nhẹ) nhanh hơn mọi câu trả lời khác r đây.
Trong .Net 3.5, thay thế EnumerateFiles bằng GetFiles (chậm hơn).

Và sử dụng nó như thế này:

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

Tôi đang sử dụng cách sau để liệt kê các file.

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

Bạn có thể sử dụng phương pháp LINQ Union:

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