我可以使用什么算法从指定的路径开始递归加载整个目录

本文关键字:加载 递归 开始 路径 什么 可以使 算法 我可以 | 更新日期: 2023-09-27 18:26:43

我正在构建一个自定义文件对话框,问题是加载时间太长。

对话框以InitialDirectory属性开始,我正在寻找一种方法,首先加载InitialDirectory的目录树,然后在后台线程中加载其余目录。

例如,如果InitialDirectoryC:'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的解决方案一个面子,实现这一点的一种方法是使用以下内容:

  1. 订阅树的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-