Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中列出目录中的大量文件#_C#_File_Directory_Enumeration - Fatal编程技术网

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

C# 在C中列出目录中的大量文件#,c#,file,directory,enumeration,C#,File,Directory,Enumeration,我正在尝试获取特定目录中的文件列表,该目录包含超过2000万个文件,每个文件的大小从2 KB到20 KB不等。 问题是,我的程序每次都抛出内存不足异常,而像robocopy这样的工具在将文件夹复制到另一个目录方面做得很好,一点问题也没有。下面是我用来枚举文件的代码: List<string> files = new List<string>(Directory.EnumerateFiles(searchDir)); List files=新列表(

我正在尝试获取特定目录中的文件列表,该目录包含超过2000万个文件,每个文件的大小从2 KB到20 KB不等。
问题是,我的程序每次都抛出内存不足异常,而像robocopy这样的工具在将文件夹复制到另一个目录方面做得很好,一点问题也没有。下面是我用来枚举文件的代码:

            List<string> files = new List<string>(Directory.EnumerateFiles(searchDir));
List files=新列表(Directory.EnumerateFiles(searchDir));
我该怎么解决这个问题?
任何帮助都将不胜感激。

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

而是使用
目录。枚举文件(searchDir)
并逐个迭代每个项目

比如:

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

见:

EnumerateFiles和GetFiles方法的区别如下: 使用EnumerateFiles,可以开始枚举 返回整个集合之前的名称当您使用 GetFiles,则必须等待返回整个名称数组 然后才能访问阵列。因此,当您与 许多文件和目录,枚举文件可以更高效


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

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));
        }                
    }
}
public IEnumerable枚举文件(字符串起始目录路径){
var directoryEnumerables=新队列();
Enqueue(新字符串[]{startingDirectoryPath});
while(directoryEnumerables.Any()){
var currentDirectoryEnumerable=directoryEnumerables.Dequeue();
foreach(currentDirectoryEnumerable中的var目录){
foreach(fileEnumeratorFunc(目录)中的var filePath){
产生返回文件路径;
}
Enqueue(Directory.EnumerateDirectories(Directory));
}                
}
}

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

不要创建文件列表。只需迭代EnumerateFiles的结果,然后做任何您想做的事情。您想在内存中保存这么多数据吗?一种方法是创建子目录并将其分组。@Rohit Yes。我试图创建一个列表,然后对它们进行迭代并进行一些处理。@JeremyMc需要查看更多代码以确定是否存在任何其他潜在的内存问题。@rory.ap这会更糟,因为它将返回一个文件数组,然后从该数组创建一个列表,因此,使用的内存量增加了一倍。这不是会遇到同样的问题吗?@rory.ap,不会。这不会在内存中加载2000万个文件路径,而是在内存中一次加载一个对象(字符串路径)memory@GillBates,否。枚举,并不意味着返回集合。这将进行惰性评估。就像
File.ReadLine
vs
File.ReadAllLines
一样。
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));
        }                
    }
}