C#如何在不使用大量内存的情况下递归循环大量文件夹和文件

C#如何在不使用大量内存的情况下递归循环大量文件夹和文件,c#,recursion,out-of-memory,fileinfo,C#,Recursion,Out Of Memory,Fileinfo,我想索引我所有的音乐文件并将它们存储在数据库中。 我有这个函数,我反复调用,从我的音乐驱动的根开始 i、 e 这很好,但在运行程序时,所使用的内存量会不断增长,并且。。最后,我的系统内存不足 有没有人有更好的方法不需要4GB的RAM来完成这项任务 很好,Tys您可以将其作为一个队列来实现。我认为(但我不确定)这会节省内存。至少它会释放你的堆栈。每当你找到一个文件夹,你就把它添加到队列中,每当你找到一个文件,你就直接读取它。这可以防止递归 大概是这样的: Queue<string> d

我想索引我所有的音乐文件并将它们存储在数据库中。 我有这个函数,我反复调用,从我的音乐驱动的根开始

i、 e

这很好,但在运行程序时,所使用的内存量会不断增长,并且。。最后,我的系统内存不足

有没有人有更好的方法不需要4GB的RAM来完成这项任务


很好,Tys

您可以将其作为一个队列来实现。我认为(但我不确定)这会节省内存。至少它会释放你的堆栈。每当你找到一个文件夹,你就把它添加到队列中,每当你找到一个文件,你就直接读取它。这可以防止递归

大概是这样的:

Queue<string> dirs = new Queue<string>();
dirs.Enqueue("basedir");
while(dirs.Count > 0) {
    foreach(directory)
        dirs.Enqueue(directory);
    ReadFiles();
}
Queue dirs=new Queue();
指令排队(“basedir”);
而(dirs.Count>0){
foreach(目录)
dirs.Enqueue(目录);
ReadFiles();
}

您是否检查了除根目录以外的每个目录中显示的
条目


如果您不跳过这些,您将有一个无限循环。

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);
}
void ReadFiles(字符串路径)
{
IEnumerable文件=
Directory.Enumerate文件(
路径
"*",
SearchOption.AllDirectories);//递归搜索
foreach(文件中的字符串文件)
SaveToIndex(文件);
}

但是,请注意,如果您无权访问文件,或者路径太长,或者发生其他异常,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;
}
公共静态列表getFiles(字符串路径,列表文件)
{
IEnumerable fileInfo=null;
IEnumerable folderInfo=null;
尝试
{
fileInfo=目录.枚举文件(str);
}
抓住
{
}
如果(fileInfo!=null)
{
files.AddRange(fileInfo);
//在子文件夹中递归
fileInfo=目录。枚举目录(str);
foreach(folderInfo中的字符串s)
{
尝试
{
获取文件;
}
抓住
{
}
}
}
归还文件;
}
示例用法:

List<string> files = new List<string>();
files = folder.getFiles(path, files);
List files=newlist();
files=folder.getFiles(路径,文件);
我的解决方案基于此页面上的代码:


更新:可以在上找到一种更快的递归获取文件的方法。使用Stack对我来说是新的(我甚至不知道它的存在),但是这个方法似乎很有效。至少它列出了我的C和D分区上的所有文件,没有任何错误。

它可能是连接文件夹,在执行递归时会导致无限循环,但我不确定,请检查并亲自查看。链接:

请发布实际代码。你的方法没有根本性的错误。递归不受可用内存的限制,而是受堆栈大小的限制,因此,如果内存不足,听起来好像你保存数据的时间太长了。我无法想象你有足够的音乐需要那么多的空间。你确定你没有得到堆栈溢出,或者在某个时刻进入了一个无止境的循环吗?请解释“保存到索引”。它是否真的将文件中的所有字节存储在正在运行的程序中的磁盘上?这不会节省内存。默认情况下,堆栈溢出之前只有1兆字节。若他要离开记忆,那个就有另一个问题了。谢谢你们的回答。一切都有所帮助。我已经实现了一个队列机制,对不应该被索引的目录做了一些额外的检查,同时我发现我的NHibernate也需要一些微调。现在可以轻松索引超过1TB的数据了。很好。我不知道:-)这是一个很好的答案,但它仍然不能解决基本问题-如果您遇到内存问题,一定是某些东西占用了太多内存。@configurator,您可能是对的。。。但根据OP提供的信息,这是我能做的最好的了;)但是,它们不会出现在
目录.GetFiles
目录.GetDirectories
中。通常,在.net中工作时不应该遇到这种情况。
List<string> files = new List<string>();
files = folder.getFiles(path, files);