在C#中的目录中列出大量文件

时间:2016-09-28 16:49:13

标签: c# file directory enumeration

我正在尝试获取特定目录中的文件列表,其中包含超过2000万个文件,每个文件的范围为2到20 KB。 问题是我的程序每次抛出Out Of Memory Exception,而robocopy等工具在将文件夹复制到另一个目录时完全没有问题。这是我用来枚举文件的代码:

            List<string> files = new List<string>(Directory.EnumerateFiles(searchDir));

我该怎么做才能解决这个问题? 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:5)

您正在内存中创建一个包含2000万个对象的列表。即使有可能,我也不认为你会使用它。

而是使用Directory.EnumerateFiles(searchDir)并逐个迭代每个项目。

像:

foreach(var file in Directory.EnumerateFiles(searchDir))
{
   //Copy to other location, or other stuff
}

使用当前代码,您的程序将首先在内存中加载2000万个对象,然后您必须迭代或对它们执行操作。

请参阅:Directory.EnumerateFiles Method (String)

  

EnumerateFiles和GetFiles方法的区别如下:当你   使用 EnumerateFiles,您可以开始枚举集合   返回整个集合之前的名称; 时使用   GetFiles,您必须等待返回整个名称数组   在您可以访问阵列之前。因此,当你在工作   许多文件和目录,EnumerateFiles可以更有效。

答案 1 :(得分:1)

以上答案涵盖了一个目录级别。为了能够枚举多个级别的目录(每个目录都有大量的目录和大量的文件),可以执行以下操作:

public IEnumerable<string> EnumerateFiles(string startingDirectoryPath) {
    var directoryEnumerables = new Queue<IEnumerable<string>>();
    directoryEnumerables.Enqueue(new string[] { startingDirectoryPath });
    while (directoryEnumerables.Any()) {
        var currentDirectoryEnumerable = directoryEnumerables.Dequeue();
        foreach (var directory in currentDirectoryEnumerable) {
            foreach (var filePath in fileEnumeratorFunc(directory)) {
                yield return filePath;
            }
            directoryEnumerables.Enqueue(Directory.EnumerateDirectories(directory));
        }                
    }
}

该函数将通过枚举器遍历目录的集合,因此它将一一加载目录内容。唯一要解决的是层次结构的深度...