从包含大量文件的目录中检索文件

本文关键字:文件 检索 包含大 | 更新日期: 2023-09-27 18:12:21

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

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

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

可以用另一种方法吗?也许读取1000个,处理它们,然后读取下一个1000个,以此类推?

从包含大量文件的目录中检索文件

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

如MSDN所说

EnumerateFilesGetFiles方法的不同之处在于使用EnumerateFiles,您可以开始枚举的集合FileInfo对象在整个集合返回之前;当你使用GetFiles时,必须等待FileInfo对象的整个数组完成在访问数组之前返回。因此,当你是EnumerateFiles可以处理许多文件和目录高效。

在。net 4.0中,Directory.EnumerateFiles(...)IEnumerable<string>(而不是Directory.GetFiles(...)string[]),所以它可以流式传输条目而不是缓冲它们;例如

foreach(var file in Directory.EnumerateFiles(path)) {
    // ...
}

您正在触及Windows文件系统本身的限制。当目录中的文件数量增长到很大数量时(14M远远超过了这个阈值),访问目录变得非常缓慢。每次读取一个文件还是读取1000个文件并不重要,它只是目录访问。

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

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

使用Win32 Api FindFile函数来完成此操作,而不会阻塞应用程序。

您也可以呼叫"通讯录"。在System.Threading.Task (TPL)中GetFiles来防止你的UI冻结

好好享受。

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

我经常遇到在单个目录中访问大文件的问题。子目录是一个很好的选择,但很快它们有时也不能提供太多帮助。我现在要做的是创建一个索引文件——一个包含目录中所有文件名称的文本文件(假设我正在该目录中创建文件)。然后读取索引文件,然后打开目录中的实际文件进行处理