2010-11-21 59 views
3

我想索引我的所有音樂文件並將它們存儲在數據庫中。 我有這個功能,我呼籲recusively,從我的音樂驅動器的根開始。C#如何遞歸循環大量文件夾和文件而不使用大量內存

start > ReadFiles(C:\music\); 

ReadFiles(path){ 
    foreach(file) 
     save to index; 

    foreach(directory) 
     ReadFiles(directory); 
} 

這工作得很好,但在運行程序時所使用的內存量增長和增長和。最後我的系統運行內存不足。

有沒有人有更好的方法,不需要4GB的RAM來完成此任務?

最好的問候,Tys

+4

請發表實際的代碼。你的方法沒有任何根本性的錯誤。 – 2010-11-21 21:03:47

+3

遞歸不受可用內存的限制,但是受堆棧大小的限制,所以如果內存不足,聽起來就像是數據持續太久。 – 2010-11-21 21:04:56

+0

我不能_imagine_你有足夠的音樂需要這麼多的空間。你確定你沒有得到堆棧溢出或者在某個時候進入了無限循環嗎? – 2010-11-21 21:05:11

回答

9

Alxandr基於隊列的解決方案應該可以正常工作。

如果你使用.NET 4.0,你也可以利用新的Directory.EnumerateFiles方法,它懶洋洋地枚舉文件,無需加載它們都在內存:

void ReadFiles(string path) 
{ 
    IEnumerable<string> files = 
     Directory.EnumerateFiles(
      path, 
      "*", 
      SearchOption.AllDirectories); // search recursively 

    foreach(string file in files) 
     SaveToIndex(file); 
} 
+0

不錯。我不知道這個:-) – Alxandr 2010-11-21 21:18:48

+0

這是一個很好的API用於這項任務。 – Brian 2010-11-21 21:20:25

+2

這是一個很好的答案,但它仍然不能解決基本問題 - 如果您遇到內存問題,必須記住太多的內存。 – configurator 2010-11-21 21:45:24

1

您可以將其實現爲一個隊列。我想(但我不確定)這會節省內存。至少它會釋放你的堆棧。只要你找到一個文件夾,你就可以將它添加到隊列中,並且只要你找到一個文件,你就可以閱讀它。這可以防止遞歸。

事情是這樣的:

Queue<string> dirs = new Queue<string>(); 
dirs.Enqueue("basedir"); 
while(dirs.Count > 0) { 
    foreach(directory) 
     dirs.Enqueue(directory); 
    ReadFiles(); 
} 
+1

這不會節省內存。默認情況下,StackOverflow之前的堆棧只有1兆字節。如果他正在使用OutOfMemory,則存在另一個問題。 – Brian 2010-11-21 21:17:09

+0

@Brian:這仍然是對原始代碼的改進...... – 2010-11-21 21:18:14

+0

感謝您的所有答案。一切都有所幫助。我已經實現了一個隊列機制,對不應該被索引的目錄做了一些額外的檢查,同時我發現我的NHibernate也需要一些微調。現在輕鬆索引超過1TB。 – Tys 2010-11-22 19:02:33

2

你檢查的...條目中除了根每個目錄顯示?

如果你不跳過這些,你將有一個無限循環。

+1

儘管它們不出現在「Directory.GetFiles」或「Directory.GetDirectories」中。 _Normally_,在.net中工作時不應該遇到這個問題。 – configurator 2010-11-21 21:44:38

0

要小心,雖然,EnumerateFiles( )將停止運行,如果您無法訪問文件或路徑太長或發生其他異常。這是我用的那一刻來解決這些問題:

public static List<string> getFiles(string path, List<string> files) 
{ 
    IEnumerable<string> fileInfo = null; 
    IEnumerable<string> folderInfo = null; 
    try 
    { 
     fileInfo = Directory.EnumerateFiles(str); 
    } 
    catch 
    { 

    } 
    if (fileInfo != null) 
    { 
     files.AddRange(fileInfo); 
     //recurse through the subfolders 
     fileInfo = Directory.EnumerateDirectories(str); 
     foreach (string s in folderInfo) 
     { 
      try 
      { 
       getFiles(s, files); 
      } 
      catch 
      { 

      } 
     } 
    } 
    return files; 
} 

使用例:

List<string> files = new List<string>(); 
files = folder.getFiles(path, files); 

我的解決方案是基於在此頁面的代碼:http://msdn.microsoft.com/en-us/library/vstudio/bb513869.aspx

更新:可以在http://social.msdn.microsoft.com/Forums/vstudio/en-US/ae61e5a6-97f9-4eaa-9f1a-856541c6dcce/directorygetfiles-gives-me-access-denied?forum=csharpgeneral找到遞歸獲得文件的更快的方法。使用Stack對我來說是新的(我甚至不知道它存在),但該方法似乎工作。至少它列出了我的C和D分區上的所有文件,沒有任何錯誤。

相關問題