66

我的目录包含近 14,000,000 个 *.wav 格式的音频样本。

所有普通存储,没有子目录。

我想遍历文件,但是当我DirectoryInfo.GetFiles()在该文件夹上使用时,整个应用程序冻结了几分钟!

这可以通过其他方式完成吗?也许读取 1000,处理它们,然后取下一个 1000 等等?

4

6 回答 6

94

您是否尝试过DirectoryInfo 类的EnumerateFiles方法?

正如 MSDN 所说

EnumerateFiles和方法的GetFiles区别如下: 使用 时EnumerateFiles,可以 FileInfo在返回整个集合之前开始枚举对象集合;使用 时GetFiles,必须等待FileInfo返回整个对象数组才能访问该数组。因此,当您处理许多文件和目录时,EnumerateFiles效率会更高。

于 2011-10-23T08:41:58.460 回答
46

在 .NET 4.0 中,Directory.EnumerateFiles(...)is IEnumerable<string>(而不是string[]of Directory.GetFiles(...)),因此它可以流式传输条目而不是全部缓冲它们;IE

foreach(var file in Directory.EnumerateFiles(path)) {
    // ...
}
于 2011-10-23T08:44:28.133 回答
19

您遇到了 Windows 文件系统本身的限制。当目录中的文件数量增长到大量时(并且 14M 远远超出了该阈值),访问目录变得异常缓慢。如果您一次读取一个文件或 1000 个文件并不重要,它只是目录访问。

解决此问题的一种方法是创建子目录并将文件分成组。如果每个目录有 1000-5000(猜测但您可以尝试实际数字),那么您应该获得不错的打开/创建/删除文件的性能。

这就是为什么如果您查看像 Doxygen 这样的应用程序,它为每个类创建一个文件,它们遵循这个方案并将所有内容放入使用随机名称的 2 级子目录中。

于 2011-10-23T08:42:25.530 回答
8

使用 Win32 Api FindFile函数在不阻塞应用程序的情况下执行此操作。

您还可以在System.Threading.Task (TPL) 中调用 Directory.GetFiles 以防止您的 UI 冻结。

于 2011-10-23T08:41:03.177 回答
5

享受。

    public List<string> LoadPathToAllFiles(string pathToFolder, int numberOfFilesToReturn)
    {
        var dirInfo = new DirectoryInfo(pathToFolder);
        var firstFiles = dirInfo.EnumerateFiles().Take(numberOfFilesToReturn).ToList();
        return firstFiles.Select(l => l.FullName).ToList();
    }
于 2014-12-15T21:59:04.930 回答
3

I hit this issue of accessing large files in a single directory a lot of the time. Sub-directories are a good option, but soon even they don't offer much help sometimes. What I now do is create an Index file - a text file with names of all the files in the directory (provided I am creating files in that directory). I then read the index file and then open then actual file from the directory for processing

于 2014-04-16T16:30:32.797 回答