2010-11-21 28 views
3

自分のすべての音楽ファイルをインデックスに登録し、データベースに格納します。 私は、私の音楽ドライブのルートから始めて、私が迂回的に呼び出すこの機能を持っています。C#膨大な量のメモリを使わずに大量のフォルダとファイルを再帰的にループする方法

すなわち

start > ReadFiles(C:\music\); 

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

    foreach(directory) 
     ReadFiles(directory); 
} 

これは正常に動作しますが、プログラムの実行中に使用されるメモリの量が成長し、成長して...最後に私のシステムがメモリ不足。

誰かがこのタスクを完了するために4GBのRAMを必要としない優れた方法がありますか?

最高のお礼、Tys

+4

実際のコードを掲載してください。根本的にあなたのアプローチに間違いはありません。 –

+3

再帰は使用可能なメモリによって制限されませんが、スタックのサイズによって制限されます。したがって、メモリが足りなくなった場合、データを長時間保持しているように見えます。 –

+0

多くのスペースを必要とするのに十分な音楽があるということを想像できません。スタックのオーバーフローが発生していないか、ある時点で無限ループに入ったことは確かですか? –

答えて

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

+0

これは、このタスクに使う良いAPIです。 – Brian

+2

これは良い答えですが、基本的な問題は解決していません。メモリの問題が発生している場合は、あまりにも多くのメモリを保持する必要があります。 – configurator

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

+0

@Brian:これはまだ元のコードよりも改善されています... –

+0

すべてのお返事ありがとうございます。すべてが少し助けました。私はキューメカニズムを実装しました。インデックスを作成しないでディレクトリをチェックしました。そのため、NHibernateには微調整が必​​要でした。 1TB以上のインデックス作成が簡単にできます。 – Tys

2

は、root以外のすべてのディレクトリに表示さ...エントリをチェックしましたか?

これらをスキップしないと、無限ループになります。

+1

これらは、 'Directory.GetFiles'や' Directory.GetDirectories'には表示されません。 _Normally_、あなたはこれに遭遇すべきではありません.netで作業しているとき。 – configurator

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

使用例:http://msdn.microsoft.com/en-us/library/vstudio/bb513869.aspx

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

私のソリューションは、このページのコードに基づいています。

更新:ファイルを再帰的に取得するための、より高速な方法は、http://social.msdn.microsoft.com/Forums/vstudio/en-US/ae61e5a6-97f9-4eaa-9f1a-856541c6dcce/directorygetfiles-gives-me-access-denied?forum=csharpgeneralにあります。スタックを使用することは私には新しく(私もそれが存在するかどうかはわかりませんでしたが)、このメソッドはうまくいくようです。少なくとも私のCとDのパーティションにエラーなしですべてのファイルがリストされていました。

関連する問題