2011-10-23 29 views
53

Tôi có thư mục chứa gần 14.000.000 mẫu âm thanh ở định dạng * .wav.Lấy các tệp từ thư mục có chứa số lượng lớn tệp

Tất cả bộ nhớ đơn giản, không có thư mục con.

Tôi muốn lặp qua các tệp, nhưng khi tôi sử dụng DirectoryInfo.GetFiles() trên thư mục đó, toàn bộ ứng dụng bị đóng băng trong vài phút!

Điều này có thể được thực hiện theo cách khác không? Có lẽ đọc 1000, xử lý chúng, sau đó tiếp theo 1000 và như vậy?

+0

'DirectoryInfo.GetFiles() 'cũng rất kinh khủng nếu bạn đang sử dụng một SAN mạng. Nó khóa tất cả các tệp và chặn người khác truy cập các tệp SAN được tạo gần đây. Chúng tôi chưa bao giờ tìm được giải pháp không chặn. – SliverNinja

+0

nếu bạn đang ở trong một điểm quan trọng thực sự hoàn hảo, tôi cũng sẽ xem xét: http://stackoverflow.com/questions/724148/is-there-a-faster-way-to-scan-through-a-directory-recursively-in -net/724184 # 724184 –

Trả lời

85

Bạn đã thử phương thức EnumerateFiles của lớp DirectoryInfo chưa?

Như MSDN Says

Các EnumerateFilesGetFiles phương pháp khác nhau như sau: Khi bạn sử dụng EnumerateFiles, bạn có thể bắt đầu liệt kê các bộ sưu tập của FileInfo đối tượng trước khi toàn bộ bộ sưu tập được trả về; khi bạn sử dụng GetFiles, bạn phải đợi toàn bộ mảng đối tượng FileInfo để được trả lại trước khi bạn có thể truy cập mảng. Do đó, khi bạn đang làm việc với nhiều tệp và thư mục, EnumerateFiles có thể có hiệu lực hơn .

+4

+1 Thú vị. Không biết nó tồn tại. Mặc dù nó gọi cùng một API nội bộ được bao bọc trong một điều tra viên tùy chỉnh. –

+0

Phương thức GetFiles của tôi chỉ trả về chuỗi chứ không phải FileInfo. – MrFox

+0

@MrFox 'chuỗi dir; ' ' Directory.GetFiles' /' Directory.EnumerateFiles' trở lại chuỗi 'mới DirectoryInfo (dir) .getFiles'/'mới DirectoryInfo (dir) .EnumerateFiles' trở FileInfo –

6

Sử dụng chức năng Win32 Api FindFile để làm điều đó mà không chặn ứng dụng.

Bạn cũng có thể gọi Directory.GetFiles theo số System.Threading.Task (TPL) để ngăn giao diện người dùng của bạn bị đóng băng.

14

bạn đang đạt đến giới hạn của hệ thống tệp Windows. Khi số lượng tệp trong một thư mục tăng lên một số lớn (và 14M vượt quá ngưỡng đó), việc truy cập thư mục trở nên cực kỳ chậm. Nó không thực sự quan trọng nếu bạn đọc một tập tin tại một thời điểm hoặc 1000, nó chỉ là truy cập thư mục.

Một cách để giải quyết điều này là tạo các thư mục con và chia nhỏ các tệp của bạn thành các nhóm. Nếu mỗi thư mục có 1000-5000 (đoán nhưng bạn có thể thử nghiệm với các con số thực tế), sau đó bạn sẽ nhận được hiệu suất phong nha mở/tạo/xóa các tập tin. Đây là lý do tại sao nếu bạn nhìn vào các ứng dụng như Doxygen, tạo ra một tập tin cho mỗi lớp, họ làm theo sơ đồ này và đặt mọi thứ vào 2 cấp độ của các thư mục con sử dụng tên ngẫu nhiên.

+0

+ 1, chính xác như vậy. Tôi sẽ thêm rằng nó tốt hơn để làm một giải pháp DB, hoặc sử dụng một hệ thống tập tin phù hợp với số lượng lớn các tập tin; chẳng hạn như ReiserFS. Tôi không chắc chắn nếu một trình điều khiển ReiserFS có sẵn cho Windows hay không. – Gleno

+0

Ví dụ tốt nhất là git đặt các đối tượng trong các thư mục có tên là hai chữ cái đầu tiên của hàm băm SHA1. – manojlds

+0

@DXM - bạn có thể cung cấp một số tài liệu tham khảo về giới hạn này không? Tôi đã luôn luôn nghĩ rằng NTFS đã không có vấn đề đối phó với các thư mục lớn (http://technet.microsoft.com/en-us/library/cc781134 (WS.10).aspx nói về 300k tập tin trong một thư mục), nhưng thám hiểm là lớn chậm lại. – ligos

40

Trong .NET 4.0, Directory.EnumerateFiles(...)IEnumerable<string> (chứ không phải là string[] của Directory.GetFiles(...)), để nó có thể truyền các mục nhập thay vì lưu tất cả chúng; tức là

foreach(var file in Directory.EnumerateFiles(path)) { 
    // ... 
} 
+3

+1 để đề cập đến .NET 4, đây là điểm quan trọng – sll

+0

Điểm thú vị ... khóa nằm trong kiểu trả về. – SliverNinja

1

Tôi đã gặp phải vấn đề này khi truy cập tệp lớn trong một thư mục. Các thư mục con là một lựa chọn tốt, nhưng ngay cả khi chúng không cung cấp nhiều trợ giúp. Những gì tôi làm bây giờ là tạo một tệp chỉ mục - một tệp văn bản có tên của tất cả các tệp trong thư mục (miễn là tôi đang tạo tệp trong thư mục đó). Sau đó tôi đọc tệp chỉ mục và sau đó mở tệp thực tế từ thư mục để xử lý

4

Tận hưởng.

public List<string> LoadPathToAllFiles(string pathToFolder, int numberOfFilesToReturn) 
    { 
     var DirInfo = new DirectoryInfo(pathToFolder); 
     var firstFiles = DirInfo.EnumerateFiles().Take(numberOfFilesToReturn).ToList(); 
     return firstFiles.Select(l => l.FullName).ToList(); 
    } 
Các vấn đề liên quan