从包含大量文件的目录中检索文件
本文关键字:文件 检索 包含大 | 更新日期: 2023-09-27 18:12:21
我有一个目录,包含近14,000,000个*.wav格式的音频样本。
所有普通存储,没有子目录。
我想循环遍历文件,但是当我在那个文件夹上使用DirectoryInfo.GetFiles()
时,整个应用程序冻结了几分钟!
可以用另一种方法吗?也许读取1000个,处理它们,然后读取下一个1000个,以此类推?
您是否尝试过DirectoryInfo类的EnumerateFiles方法?
如MSDN所说
EnumerateFiles
和GetFiles
方法的不同之处在于使用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();
}
我经常遇到在单个目录中访问大文件的问题。子目录是一个很好的选择,但很快它们有时也不能提供太多帮助。我现在要做的是创建一个索引文件——一个包含目录中所有文件名称的文本文件(假设我正在该目录中创建文件)。然后读取索引文件,然后打开目录中的实际文件进行处理