我可以使用什么算法从指定的路径开始递归加载整个目录
本文关键字:加载 递归 开始 路径 什么 可以使 算法 我可以 | 更新日期: 2023-09-27 18:26:43
我正在构建一个自定义文件对话框,问题是加载时间太长。
对话框以InitialDirectory
属性开始,我正在寻找一种方法,首先加载InitialDirectory
的目录树,然后在后台线程中加载其余目录。
例如,如果InitialDirectory
是C:'Users'User12345'MyDocuments
,那么它应该加载中的所有文件夹
C:''C: ''用户C: ''用户12345C: ''Users''User12345''MyDocuments
然后启动一个后台线程来加载所有剩余的目录。
有没有一种快速简单的方法可以使用递归首先加载InitialDirectory
,而不是其他任何东西,而不复制任何项目?
我很难找到一种高性能的方法来做到这一点,因为使用if (!Directory.Contains(f => f.FullName == folder.FullName))
这样的代码检查文件夹的存在会大大降低加载速度。
我当前加载完整目录的代码如下所示:
private void LoadDirectory()
{
string root = @"C:'";
var rootNode = new DirectoryModel() { Name = root, FullName = root };
this.Directory.Add(rootNode);
DirectoryInfo info = new DirectoryInfo(root);
IEnumerable<DirectoryInfo> subDirectories = info.GetDirectories()
.Where(d => ((d.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
&& ((d.Attributes & FileAttributes.System) != FileAttributes.System));
LoadDirectories(subDirectories, root);
}
private void LoadDirectories(IEnumerable<DirectoryInfo> subDirs, string parentName)
{
IEnumerable<DirectoryInfo> subdirectories;
foreach (DirectoryInfo folder in subDirs)
{
var node = new DirectoryModel() { Name = folder.Name, FullName = folder.FullName, ParentName = parentName };
Directory.Add(node);
try
{
subdirectories = folder.GetDirectories("*", SearchOption.TopDirectoryOnly)
.Where(d => ((d.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
&& ((d.Attributes & FileAttributes.System) != FileAttributes.System));
}
catch (UnauthorizedAccessException e)
{
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
continue;
}
if (subdirectories.Count() != 0)
LoadDirectories(subdirectories, folder.FullName);
}
}
请注意,Directory
集合是一个平面集合——数据模型中没有层次结构。
这取决于如何向用户展示您的数据imo.
如果使用TreeView
控件,可以很容易地避免在后台加载所有数据,而只加载树的根(就像我所理解的那样)。
这样,在加载指定目录的所有子目录名和文件的过程中,您只需要等待用户单击[+]
,即可查看他感兴趣的目录内容。因此,您运行过程并填充树。
这实际上是我所知道的处理这类东西的最高性能的方式,实际上你会在几乎所有"类似探险家"的产品中发现这种模式。这里的性能不是通过完美的算法实现的,而是通过定义更方便的行为模型实现的。
希望这能有所帮助。
要给Tigran的解决方案一个面子,实现这一点的一种方法是使用以下内容:
-
订阅树的BeforeExpand事件。
private void BeforeExpand(object sender, BeforeExpandEventArgs e) { TreeListNode current = e.Node; if (current.Nodes.Count > 0) return; if (current.Tag is DriveInfo) { exampleTree.BeginUpdate(); DriveInfo driveInfo = current.Tag as DriveInfo; LoadDirectories(current, driveInfo.RootDirectory); exampleTree.EndUpdate(true); } else if (current.Tag is DirectoryInfo) { exampleTree.BeginUpdate(); LoadDirectories(current, (DirectoryInfo)current.Tag); exampleTree.EndUpdate(true); } }
这里是LoadDirectories()方法:
private void LoadDirectories(TreeListNode parent, DirectoryInfo directoryInfo)
{
DirectoryInfo[] directories = directoryInfo.GetDirectories();
foreach (DirectoryInfo directory in directories)
{
if ((directory.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
TreeListNode child = new TreeListNode() { Tag = directory, Text = directory.Name };
parent.Nodes.Add(child);
}
FileInfo[] files = directoryInfo.GetFiles();
foreach (FileInfo file in files)
{
TreeListNode child = new TreeListNode() { Tag = file, Text = file.Name };
parent.Nodes.Add(child);
}
}
HTH,
-saige-