使用Linq获取目录结构?

时间:2009-04-29 21:01:13

标签: c# .net linq

我有一个应用程序,我在计算机上获得驱动器列表,当您选择一个驱动器时,我使用目录和文件填充树控件。

我正在考虑使用linq来循环遍历每个目录并获取其子目录。

以前有人做过这样的事吗?

由于

6 个答案:

答案 0 :(得分:2)

以下是如何做到这一点的示例: Using-LINQ-to-access-the-file-system

这是另一个:How-to-search-the-file-system-using-linq-queries

答案 1 :(得分:2)

你可以使用LINQ没问题,虽然这是一个足够简单的任务,文件系统相关的代码可能比LINQ相关的代码更长:

    private static TreeNode AddDirectory(DirectoryInfo directory)
{
    DirectoryInfo[] subdirs = directory.GetDirectories();
    FileInfo[] files = directory.GetFiles();
    IEnumerable<TreeNode> subdirNodes = from subdir in subdirs select AddDirectory(subdir);
    IEnumerable<TreeNode> fileNodes = from file in files select new TreeNode(file.Name);
    return new TreeNode(
        directory.Name, 
        subdirNodes.Concat(fileNodes).ToArray());
}

答案 2 :(得分:1)

顺便说一句 - 您可能有兴趣知道.NET 4.0正在内置LINQ启用文件操作(适当的懒惰,显然 - 不是juts遍历数组)。在此BCL Team Blog条目中查找“文件系统枚举改进”。

答案 3 :(得分:0)

通常,当UI显示文件和文件夹树时,它不会一次扫描整个层次结构。相反,它会为扩展的节点收集足够的信息。然后,当用户扩展节点时,它会努力找出需要在该节点下放置的内容。

原因很简单,因为许多人的系统驱动器上的文件和目录数量会变得非常大,因此如果他们要求查看驱动器C的根目录,你的应用程序会冻结一段时间。

根据您使用的是WPF还是Windows窗体,它会略有不同。在WPF中,Expanded事件位于TreeViewItem本身,而在Windows窗体中,TreeView上有几个扩展事件(TreeNode上没有事件)。但模式大致相同。

添加表示文件夹的树节点时,在其下创建一个虚拟节点。给它一些特殊标识(Tag属性中的特殊标志,或者可能是包含无效文件系统字符的唯一名称)。这将允许用户扩展该节点。然后在您的扩展事件处理程序中,查看第一个子节点 - 如果它是特殊虚拟节点,则将其删除,然后为该节点创建真实的子节点集。这将确保您每个目录只收集一次真实节点。

这是WPF的一个粗略想法:

TreeViewItem folderNode = new TreeViewItem { Header = Path.GetFileName(folderPath) };
parentNode.Items.Add(folderNode);

// create the dummy item under it
TreeViewItem dummy = new TreeViewItem { Tag = _dummyTag };
folderNode.Items.Add(dummy);

folderNode.Expanded += delegate
    {
        if (folderNode.Items.Count == 1)
        {
            if (((TreeViewItem)folderNode.Items[0]).Tag == _dummyTag)
            {
                folderNode.Items.Clear();
                CreateFolderChildren(folderNode, folderPath);
            }
        }
    };

_dummyTag可以只是一个字段:

private static readonly object _dummyTag = new object();

答案 4 :(得分:0)

让我再次皮条客我的tree extensions:)

样品:

var di = new DirectoryInfo("foo");
var q = di.TraverseDepthFirst( x => x.GetFiles(), x => x.GetDirectories());
var nq = from fs in q
         from f in fs
         select f;

foreach (FileInfo dirfiles in nq)
{
  ...
}

答案 5 :(得分:0)

如果您使用GetFiles,您将启动一个将返回数组的阻止操作。如果您改为使用EnumerateFiles,则会得到延迟评估,允许您在从文件系统返回所有文件之前开始工作。更多LINQy。

E.g:

var files = directory.EnumerateFiles();
foreach (var file in files)
{
    // do stuff
}