Bạn có thể gọi Directory.GetFiles () với nhiều bộ lọc không?


353

Tôi đang cố gắng sử dụng Directory.GetFiles()phương thức để lấy danh sách các tệp có nhiều loại, chẳng hạn như mp3's và jpg'. Tôi đã thử cả hai điều sau đây nhưng không có may mắn:

Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);

Có cách nào để làm điều này trong một cuộc gọi không?


3
Là một lưu ý phụ, sử dụng mẫu tìm kiếm GetFiles để lọc tiện ích mở rộng không an toàn. Ví dụ: bạn có hai tệp Test1.xls và Test2.xlsx và bạn muốn lọc tệp xls bằng mẫu tìm kiếm * .xls, nhưng GetFiles trả về cả Test1 .xls và Test2.xlsx. Đọc phần Ghi chú để biết thêm thông tin
kiran 7/12/13

Vậy làm thế nào để ngăn chặn điều này?
Chân đế

2
@kiran Làm thế nào là không an toàn? Trông giống như một tính năng hơn là một lỗi.
Kyle Delaney

Câu trả lời:


519

Đối với .NET 4.0 trở lên,

var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
            .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

Đối với các phiên bản trước của .NET,

var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories)
            .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

chỉnh sửa: Xin vui lòng đọc các ý kiến. Sự cải thiện mà Paul Farry gợi ý, và vấn đề về trí nhớ / hiệu suất mà Christian.K chỉ ra đều rất quan trọng.


10
Man, tôi phải suy nghĩ về LINQ thường xuyên hơn. Giải pháp tốt đẹp!
Ken Pespisa

61
Chỉ cần đảm bảo rằng bạn hiểu ý nghĩa mặc dù: điều này sẽ trả về tất cả các tệp trong một chuỗi chuỗi và sau đó lọc nó bằng các phần mở rộng bạn chỉ định. Đó có thể không phải là vấn đề lớn nếu "C: \ Path" không có nhiều tệp bên dưới nó, nhưng có thể là vấn đề về bộ nhớ / hiệu năng trên "C: \" hoặc đại loại như thế.
Christian.K

24
... 2 năm sau: Mã đẹp, nhưng hãy cẩn thận với điều này, nếu bạn có một tệp kết thúc bằng .JPG thì nó sẽ không tạo được. Thêm tốt hơns.ToLower().Endswith...
Stormenet

107
bạn chỉ có thể sử dụngs.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Paul Farry

119
Lưu ý rằng với .NET 4.0, bạn có thể thay thế Directory.GetFilesbằng Directory.EnumerateFiles, msdn.microsoft.com/en-us/l Library / dd383571.aspx , điều này sẽ tránh được các vấn đề về bộ nhớ mà @ Christian.K đề cập.
Jim Mischel

60

Còn cái này thì sao:

private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
{
   return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray();
}

Tôi tìm thấy nó ở đây (trong các ý kiến): http://msdn.microsoft.com/en-us/l Library / wz42302f.aspx


Tôi đoán điều này sẽ tránh những cạm bẫy bộ nhớ tiềm năng của câu trả lời được xếp hạng hàng đầu? Trong trường hợp đó, nó nên được đánh giá cao hơn!
Dan W

11
@DanW Câu trả lời được xếp hạng hàng đầu chắc chắn gây gánh nặng cho bộ nhớ nhưng tôi nghĩ đó không phải là vấn đề như vậy. Tôi cũng thích câu trả lời này, nhưng thực ra nó chậm hơn nhiều so với câu trả lời được chấp nhận. Kiểm tra SpeedTest
OttO

Cảm ơn. Vui mừng khi thấy nó chỉ chậm hơn khoảng hai lần - tôi sẽ gắn bó với nó trong thời gian đó tôi nghĩ.
Dan W

7
Nó chỉ chậm gấp đôi nếu chỉ có hai phần mở rộng. Nếu bạn có một danh sách các phần mở rộng X, thì nó sẽ chậm hơn X lần. Bởi vì ở đây bạn đang gọi hàm Directory.GetFiles nhiều lần, trong khi trong giải pháp khác, nó chỉ được gọi một lần.
Oscar Hermosilla

1
@OscarHermosilla Người ta có thể sử dụng Parallel.ForEachđể có được chúng song song
FindOutIslamNow

33

Nếu bạn có một danh sách lớn các tiện ích mở rộng để kiểm tra, bạn có thể sử dụng các mục sau. Tôi không muốn tạo ra nhiều câu lệnh OR vì vậy tôi đã sửa đổi những gì lette đã viết.

string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08";
foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
{
    //do work here
}

Làm ơn giúp tôi với cái này ... Khi tôi in imageFile, nó sẽ đưa ra toàn bộ đường dẫn của nó. Làm thế nào tôi có thể thu nhỏ nó thành tên của tệp.
Naresh

1
System.IO.Path.GetFileName (imageFile)
jnoreiga

Path.GetExtensiontrả về '.ext', không phải '* .ext' (ít nhất là trong 3,5+).
nullable

2
FYI: Bạn cần System.Linq cho .where (
jnoreiga

1
Có một lỗ hổng tiềm năng. Chúng tôi đã qua những ngày mà các tiện ích mở rộng được yêu cầu phải có chính xác ba ký tự. Giả sử bạn có thể gặp một tệp có .abcvà được hỗ trợExtensions .abcd. Sẽ phù hợp, mặc dù nó không nên. Để sửa: supportedExtensions = ".jpg|.abcd|";với .Contains(Path.GetExtension(s).ToLower() + "|"). Đó là, bao gồm nhân vật phân tách của bạn trong thử nghiệm. QUAN TRỌNG: ký tự dấu tách của bạn cũng phải nằm sau mục LAST trong hỗ trợ Ngoại lệ.
ToolmakerSteve

31

cho

var exts = new[] { "mp3", "jpg" };

Bạn có thể:

public IEnumerable<string> FilterFiles(string path, params string[] exts) {
    return
        Directory
        .EnumerateFiles(path, "*.*")
        .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}

Nhưng lợi ích thực sự của việc EnumerateFileshiển thị khi bạn tách các bộ lọc và hợp nhất các kết quả:

public IEnumerable<string> FilterFiles(string path, params string[] exts) {
    return 
        exts.Select(x => "*." + x) // turn into globs
        .SelectMany(x => 
            Directory.EnumerateFiles(path, x)
            );
}

Sẽ nhanh hơn một chút nếu bạn không phải biến chúng thành những khối u (tức là exts = new[] {"*.mp3", "*.jpg"} đã có).

Đánh giá hiệu suất dựa trên thử nghiệm LinqPad sau đây (lưu ý: Perfchỉ cần lặp lại 10000 lần đại biểu) https://gist.github.com/zaus/7454021

(đăng lại và mở rộng từ 'trùng lặp' vì câu hỏi đó đặc biệt yêu cầu không có LINQ: Nhiều phần mở rộng tệp tìm kiếm Mô hình cho System.IO.Directory.GetFiles )


bạn có ý gì khi nói "tôi sẽ nhanh hơn một chút nếu bạn không phải biến chúng thành những khối u ám"? Là O (1) hay là O (n) (liên quan đến số lượng tệp chứ không phải số lượng tiện ích mở rộng)? Tôi đã đoán nó là O (1) (hoặc O (n) liên quan đến số lượng tiện ích mở rộng) và có lẽ ở đâu đó trong phạm vi của một vài chu kỳ cpu ... Nếu đó là trường hợp có lẽ - hiệu suất khôn ngoan - không đáng kể
BatteryBackupUnit

@BatteryBackupUnit yeah với 10k reps so với 2 phần mở rộng, chênh lệch toàn cầu so với str là 3ms, vì vậy, về mặt kỹ thuật không đáng kể (xem liên kết kết quả hoàn hảo), nhưng không biết có bao nhiêu phần mở rộng bạn cần lọc để tôi nhận ra rằng nó đáng để chỉ ra rằng có một Sự khác biệt; tôi để bạn quyết định xem "sử dụng đơn giản hóa" (nghĩa là .FilterFiles(path, "jpg", "gif")) có tốt hơn "những lời nói rõ ràng" (tức là .FilterFiles(path, "*.jpg", "*.gif")) không.
drzaus

hoàn hảo, cảm ơn Xin lỗi tôi bằng cách nào đó đã bỏ qua liên kết github đó. Có lẽ tôi nên điều chỉnh cài đặt màu màn hình của mình :)
BatteryBackupUnit

Điều này có hỗ trợ mở rộng chữ hoa như ass .JPG hoặc .MKV không?
Wahyu

1
Lỗ hổng với giải pháp SelectMany là nó sẽ lặp lại trên tất cả các tệp một lần cho mỗi phần mở rộng tệp được truyền vào.
17 trên 26 tháng

16

Tôi biết đó là câu hỏi cũ nhưng LINQ: (.NET40 +)

var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));

3
Ý tưởng tốt. Xem xét sử dụng file.ToLower()để dễ dàng phù hợp với phần mở rộng chữ hoa. Và tại sao không trích xuất phần mở rộng trước, vì vậy Regex không phải kiểm tra toàn bộ đường dẫn: Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
ToolmakerSteve

13

Ngoài ra còn có một giải pháp gốc mà dường như không có bất kỳ bộ nhớ hoặc hiệu năng nào và khá thanh lịch:

string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();

1
Tôi cho rằng tôi có thể chỉnh sửa nó để nó chấp nhận số lượng tiện ích mở rộng không giới hạn không xác định với biến chuỗi mới và hàm Split. Nhưng ngay cả khi đó, làm thế nào điều này tốt hơn giải pháp của jnoreiga? Có nhanh hơn không? Tiêu thụ bộ nhớ ít hơn?
Chân đế

1
Có một sự đánh đổi. Cách tiếp cận này gọi GetFiles nhiều lần, mỗi lần một bộ lọc. Nhiều cuộc gọi đó có thể là "chi phí hiệu năng" đáng kể trong một số trường hợp, Nó có một lợi thế quan trọng là mỗi GetFiles chỉ trả về một mảng với các đường dẫn tệp phù hợp . Tôi hy vọng điều này thường là một kết quả hoạt động tốt, thậm chí có thể là hiệu suất vượt trội , nhưng điều đó cần phải được kiểm tra. Nếu GetFiles nhanh hơn đáng kể so với Enum CảFiles, thì đây có thể là cách tiếp cận tốt nhất. Cũng lưu ý rằng ".ToArray ()" cuối cùng có thể được bỏ qua khi IEnumerable có thể sử dụng trực tiếp.
ToolmakerSteve

11

Một cách khác để sử dụng Linq, nhưng không phải trả lại mọi thứ và lọc trên đó trong bộ nhớ.

var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories));

Đó thực sự là 2 cuộc gọi GetFiles(), nhưng tôi nghĩ nó phù hợp với tinh thần của câu hỏi và trả lại chúng trong một số lượng lớn.


Tại sao nên sử dụng Linq? Nó sẽ nhanh hơn việc sử dụng Danh sách và addrange?
ThunderGr

1
tôi không biết cái gì sẽ nhanh hơn và đừng nghĩ đó là một câu hỏi quan trọng. đối với hầu hết mọi nơi bạn đang sử dụng mã cho bất kỳ giải pháp nào cho vấn đề này, sự khác biệt về hiệu suất sẽ không đáng kể. câu hỏi nên là những gì dễ đọc hơn để giảm bớt khả năng duy trì của mã trong tương lai. Tôi nghĩ rằng đây là một câu trả lời hợp lý bởi vì nó đặt vào một dòng nguồn, mà tôi nghĩ là một phần của những gì câu hỏi mong muốn, các cuộc gọi cần thiết và thể hiện rõ ràng ý định của dòng đó. danh sách và addrange gây mất tập trung với nhiều bước để thực hiện cùng một điều.
Dave Rael

7

Không. Hãy thử như sau:

List<string> _searchPatternList = new List<string>();
    ...
    List<string> fileList = new List<string>();
    foreach ( string ext in _searchPatternList )
    {
        foreach ( string subFile in Directory.GetFiles( folderName, ext  )
        {
            fileList.Add( subFile );
        }
    }

    // Sort alpabetically
    fileList.Sort();

    // Add files to the file browser control    
    foreach ( string fileName in fileList )
    {
        ...;
    }

Lấy từ: http://bloss.msdn.com/markda/archive/2006/04/20/580075.aspx


7

Để cho

var set = new HashSet<string> { ".mp3", ".jpg" };

Sau đó

Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
         .Where(f => set.Contains(
             new FileInfo(f).Extension,
             StringComparer.OrdinalIgnoreCase));

hoặc là

from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
from ext in set
where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase)
select file;

getfiles không có quá tải u được đăng.
nawfal

5

Tôi không thể sử dụng .Where phương pháp vì tôi đang lập trình trong .NET Framework 2.0 (Linq chỉ được hỗ trợ trong .NET Framework 3.5+).

Mã dưới đây không phân biệt chữ hoa chữ thường (vì vậy .CaBhoặc .cabsẽ được liệt kê quá).

string[] ext = new string[2] { "*.CAB", "*.MSU" };

foreach (string found in ext)
{
    string[] extracted = Directory.GetFiles("C:\\test", found, System.IO.SearchOption.AllDirectories);

    foreach (string file in extracted)
    {
        Console.WriteLine(file);
    }
}

4

Hàm sau tìm kiếm trên nhiều mẫu, được phân tách bằng dấu phẩy. Bạn cũng có thể chỉ định loại trừ, ví dụ: "! Web.config" sẽ tìm kiếm tất cả các tệp và loại trừ "web.config". Các mẫu có thể được trộn lẫn.

private string[] FindFiles(string directory, string filters, SearchOption searchOption)
{
    if (!Directory.Exists(directory)) return new string[] { };

    var include = (from filter in filters.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim());
    var exclude = (from filter in include where filter.Contains(@"!") select filter);

    include = include.Except(exclude);

    if (include.Count() == 0) include = new string[] { "*" };

    var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", @"\.").Replace("*", ".*").Replace("?", "."));
    Regex regex = new Regex(string.Join("|", rxfilters.ToArray()));

    List<Thread> workers = new List<Thread>();
    List<string> files = new List<string>();

    foreach (string filter in include)
    {
        Thread worker = new Thread(
            new ThreadStart(
                delegate
                {
                    string[] allfiles = Directory.GetFiles(directory, filter, searchOption);
                    if (exclude.Count() > 0)
                    {
                        lock (files)
                            files.AddRange(allfiles.Where(p => !regex.Match(p).Success));
                    }
                    else
                    {
                        lock (files)
                            files.AddRange(allfiles);
                    }
                }
            ));

        workers.Add(worker);

        worker.Start();
    }

    foreach (Thread worker in workers)
    {
        worker.Join();
    }

    return files.ToArray();

}

Sử dụng:

foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
            {
                Console.WriteLine(file);
            }

4
List<string> FileList = new List<string>();
DirectoryInfo di = new DirectoryInfo("C:\\DirName");

IEnumerable<FileInfo> fileList = di.GetFiles("*.*");

//Create the query
IEnumerable<FileInfo> fileQuery = from file in fileList
                                  where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png")
                                  orderby file.LastWriteTime
                                  select file;

foreach (System.IO.FileInfo fi in fileQuery)
{
    fi.Attributes = FileAttributes.Normal;
    FileList.Add(fi.FullName);
}

file.Extension.ToLower()là thực hành xấu.
abatishchev

Vậy thì chúng ta nên sử dụng cái gì? @abatishchev
Nitin

@Nitin:String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
abatishchev

1
Trên thực tế, file.Extension.Equals (". Jpg", StringComparison.OrdinalIgnoreCase) là những gì tôi thích. Nó dường như nhanh hơn .ToLower hoặc .ToUpper, hoặc do đó họ nói ở mọi nơi tôi tìm kiếm. Trên thực tế, .Equals cũng nhanh hơn ==, vì == gọi .Equals kiểm tra null (Vì bạn không thể thực hiện null.Equals (null)).
ThunderGr

4

trong .NET 2.0 (không có Linq):

public static List<string> GetFilez(string path, System.IO.SearchOption opt,  params string[] patterns)
{
    List<string> filez = new List<string>();
    foreach (string pattern in patterns)
    {
        filez.AddRange(
            System.IO.Directory.GetFiles(path, pattern, opt)
        );
    }


    // filez.Sort(); // Optional
    return filez; // Optional: .ToArray()
}

Sau đó sử dụng nó:

foreach (string fn in GetFilez(path
                             , System.IO.SearchOption.AllDirectories
                             , "*.xml", "*.xml.rels", "*.rels"))
{}

4
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();

3

Chỉ cần tìm một cách khác để làm điều đó. Vẫn không phải là một thao tác, nhưng ném nó ra để xem người khác nghĩ gì về nó.

private void getFiles(string path)
{
    foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch))
    {
        Debug.Print(s);
    }
}

private bool predicate_FileMatch(string fileName)
{
    if (fileName.EndsWith(".mp3"))
        return true;
    if (fileName.EndsWith(".jpg"))
        return true;
    return false;
}

3

Thế còn

string[] filesPNG = Directory.GetFiles(path, "*.png");
string[] filesJPG = Directory.GetFiles(path, "*.jpg");
string[] filesJPEG = Directory.GetFiles(path, "*.jpeg");

int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length;
List<string> filesAll = new List<string>(totalArraySizeAll);
filesAll.AddRange(filesPNG);
filesAll.AddRange(filesJPG);
filesAll.AddRange(filesJPEG);

2

Tạo các phần mở rộng bạn muốn một chuỗi tức là ".mp3.jpg.wma.wmf" và sau đó kiểm tra xem mỗi tệp có chứa phần mở rộng bạn muốn không. Điều này hoạt động với .net 2.0 vì nó không sử dụng LINQ.

string myExtensions=".jpg.mp3";

string[] files=System.IO.Directory.GetFiles("C:\myfolder");

foreach(string file in files)
{
   if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower()))
   {
      //this file has passed, do something with this file

   }
}

Ưu điểm của phương pháp này là bạn có thể thêm hoặc xóa tiện ích mở rộng mà không cần chỉnh sửa mã tức là để thêm hình ảnh png, chỉ cần viết myExtensions = ". Jpg.mp3.png".


nó không biết nó là gìs
Chân đế

2
/// <summary>
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// </summary>
/// <param name="srcDirs">The directories to seach</param>
/// <param name="searchPatterns">the list of search patterns</param>
/// <param name="searchOption"></param>
/// <returns>The list of files that match the specified pattern</returns>
public static string[] GetFilesUsingLINQ(string[] srcDirs,
     string[] searchPatterns,
     SearchOption searchOption = SearchOption.AllDirectories)
{
    var r = from dir in srcDirs
            from searchPattern in searchPatterns
            from f in Directory.GetFiles(dir, searchPattern, searchOption)
            select f;

    return r.ToArray();
}

2

Không ... Tôi tin rằng bạn phải thực hiện nhiều cuộc gọi như loại tệp bạn muốn.

Tôi sẽ tự tạo một hàm lấy một chuỗi trên các chuỗi với các phần mở rộng tôi cần và sau đó lặp lại trên mảng đó để thực hiện tất cả các cuộc gọi cần thiết. Hàm đó sẽ trả về một danh sách chung các tệp khớp với các tiện ích mở rộng tôi đã gửi.

Hy vọng nó giúp.


1

Tôi gặp vấn đề tương tự và không thể tìm ra giải pháp phù hợp nên tôi đã viết một hàm có tên GetFiles:

/// <summary>
/// Get all files with a specific extension
/// </summary>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>array of all the files with the specific extensions</returns>
public string[] GetFiles(List<string> extensionsToCompare, string Location)
{
    List<string> files = new List<string>();
    foreach (string file in Directory.GetFiles(Location))
    {
        if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.')+1).ToLower())) files.Add(file);
    }
    files.Sort();
    return files.ToArray();
}

Chức năng này sẽ Directory.Getfiles()chỉ gọi một lần.

Ví dụ gọi hàm như thế này:

string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");

EDIT: Để có được một tệp có nhiều tiện ích mở rộng, hãy sử dụng tệp này:

/// <summary>
    /// Get the file with a specific name and extension
    /// </summary>
    /// <param name="filename">the name of the file to find</param>
    /// <param name="extensionsToCompare">string list of all the extensions</param>
    /// <param name="Location">string of the location</param>
    /// <returns>file with the requested filename</returns>
    public string GetFile( string filename, List<string> extensionsToCompare, string Location)
    {
        foreach (string file in Directory.GetFiles(Location))
        {
            if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf('.') - (Location.Length + 1))).ToLower() == filename) 
                return file;
        }
        return "";
    }

Ví dụ gọi hàm như thế này:

string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");

1

Tôi tự hỏi tại sao có rất nhiều "giải pháp" được đăng?

Nếu hiểu biết về tân binh của tôi về cách GetFiles hoạt động là đúng, chỉ có hai tùy chọn và bất kỳ giải pháp nào ở trên có thể được đưa ra dưới đây:

  1. GetFiles, sau đó lọc: Nhanh, nhưng một trình diệt bộ nhớ do lưu trữ trên đầu cho đến khi các bộ lọc được áp dụng

  2. Lọc trong khi GetFiles: Làm chậm các bộ lọc hơn được đặt, nhưng sử dụng bộ nhớ thấp vì không có chi phí nào được lưu trữ.
    Điều này được giải thích trong một trong những bài đăng trên với điểm chuẩn ấn tượng: Mỗi tùy chọn bộ lọc gây ra hoạt động GetFile riêng biệt để cùng một phần của ổ cứng được đọc nhiều lần.

Theo tôi, Tùy chọn 1) tốt hơn, nhưng sử dụng SearchOption.AllDirectories trên các thư mục như C: \ sẽ sử dụng một lượng lớn bộ nhớ.
Do đó tôi sẽ chỉ thực hiện một phương thức đệ quy đi qua tất cả các thư mục con bằng cách sử dụng tùy chọn 1)

Điều này sẽ chỉ gây ra 1 hoạt động GetFiles trên mỗi thư mục và nhanh chóng (Tùy chọn 1), nhưng chỉ sử dụng một lượng bộ nhớ nhỏ vì các bộ lọc được áp dụng sau mỗi lần đọc của thư mục con -> chi phí bị xóa sau mỗi thư mục con.

Xin hãy sửa tôi nếu tôi sai. Tôi đã nói khá mới về lập trình nhưng muốn hiểu sâu hơn về mọi thứ để cuối cùng trở nên giỏi về việc này :)


1

Nếu bạn đang sử dụng VB.NET (hoặc nhập phụ thuộc vào dự án C # của bạn), thực sự tồn tại một phương thức tiện lợi cho phép lọc nhiều tiện ích mở rộng:

Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});

Trong VB.NET, điều này có thể được truy cập thông qua không gian tên của tôi:

My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})

Thật không may, các phương pháp tiện lợi này không hỗ trợ một biến thể được đánh giá lười biếng như thế Directory.EnumerateFiles().


Đây dễ dàng là câu trả lời tốt nhất và một điều khó khăn hơn nhiều là câu trả lời được chấp nhận. Phải yêu SO.
Robbie Coyne

0

Tôi không biết giải pháp nào tốt hơn, nhưng tôi sử dụng giải pháp này:

String[] ext = "*.ext1|*.ext2".Split('|');

            List<String> files = new List<String>();
            foreach (String tmp in ext)
            {
                files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories));
            }

0

Đây là một cách đơn giản và thanh lịch để nhận các tệp được lọc

var allowedFileExtensions = ".csv,.txt";


var files = Directory.EnumerateFiles(@"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly)
                .Where(s => allowedFileExtensions.IndexOf(Path.GetExtension(s)) > -1).ToArray(); 

-1

Hoặc bạn chỉ có thể chuyển đổi chuỗi tiện ích mở rộng thành Chuỗi ^

vector <string>  extensions = { "*.mp4", "*.avi", "*.flv" };
for (int i = 0; i < extensions.size(); ++i)
{
     String^ ext = gcnew String(extensions[i].c_str());;
     String^ path = "C:\\Users\\Eric\\Videos";
     array<String^>^files = Directory::GetFiles(path,ext);
     Console::WriteLine(ext);
     cout << " " << (files->Length) << endl;
}

2
Đây là c ++ chứ không phải c #
Chân đế

-1

Sử dụng mẫu tìm kiếm GetFiles để lọc tiện ích mở rộng không an toàn !! Chẳng hạn, bạn có hai tệp Test1.xls và Test2.xlsx và bạn muốn lọc tệp xls bằng mẫu tìm kiếm * .xls, nhưng GetFiles trả về cả Test1.xls và Test2.xlsx Tôi không biết điều này và gặp lỗi khi sản xuất môi trường khi một số tập tin tạm thời đột nhiên được xử lý như tập tin bên phải. Mẫu tìm kiếm là * .txt và các tệp tạm thời được đặt tên * .txt20181028_100753898 Vì vậy, mẫu tìm kiếm không thể tin cậy được, bạn cũng phải thêm kiểm tra tên tệp.


Không trả lời câu hỏi.
Robbie Coyne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.