我的目录包含近 14,000,000 个 *.wav 格式的音频样本。
所有普通存储,没有子目录。
我想遍历文件,但是当我DirectoryInfo.GetFiles()
在该文件夹上使用时,整个应用程序冻结了几分钟!
这可以通过其他方式完成吗?也许读取 1000,处理它们,然后取下一个 1000 等等?
您是否尝试过DirectoryInfo 类的EnumerateFiles方法?
正如 MSDN 所说
EnumerateFiles
和方法的GetFiles
区别如下: 使用 时EnumerateFiles
,可以FileInfo
在返回整个集合之前开始枚举对象集合;使用 时GetFiles
,必须等待FileInfo
返回整个对象数组才能访问该数组。因此,当您处理许多文件和目录时,EnumerateFiles
效率会更高。
在 .NET 4.0 中,Directory.EnumerateFiles(...)
is IEnumerable<string>
(而不是string[]
of Directory.GetFiles(...)
),因此它可以流式传输条目而不是全部缓冲它们;IE
foreach(var file in Directory.EnumerateFiles(path)) {
// ...
}
您遇到了 Windows 文件系统本身的限制。当目录中的文件数量增长到大量时(并且 14M 远远超出了该阈值),访问目录变得异常缓慢。如果您一次读取一个文件或 1000 个文件并不重要,它只是目录访问。
解决此问题的一种方法是创建子目录并将文件分成组。如果每个目录有 1000-5000(猜测但您可以尝试实际数字),那么您应该获得不错的打开/创建/删除文件的性能。
这就是为什么如果您查看像 Doxygen 这样的应用程序,它为每个类创建一个文件,它们遵循这个方案并将所有内容放入使用随机名称的 2 级子目录中。
使用 Win32 Api FindFile函数在不阻塞应用程序的情况下执行此操作。
您还可以在System.Threading.Task (TPL) 中调用 Directory.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();
}
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