2

我正在尝试使用以下方法列出根目录的所有子目录中的文件。但是当文件数量以百万计时,它需要很长时间。有没有更好的方法来做到这一点。

我正在使用.NET 3.5,所以不能使用枚举器:-(

        ******************* Main *************
        DirectoryInfo dir = new DirectoryInfo(path);
        DirectoryInfo[] subDir = dir.GetDirectories();
        foreach (DirectoryInfo di in subDir) //call for each sub directory
        {
             PopulateList(di.FullName, false);
        }

        *******************************************
        static void PopulateList(string directory, bool IsRoot)
        {

            System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "dir /s/b \"" + directory + "\"");
            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo = procStartInfo;
            proc.Start();

            string fileName = directory.Substring(directory.LastIndexOf('\\') + 1);
            StreamWriter writer = new StreamWriter(fileName + ".lst");

            while (proc.StandardOutput.EndOfStream != true)
            {
                 writer.WriteLine(proc.StandardOutput.ReadLine());
                 writer.Flush();
            }
            writer.Close();
        }
4

5 回答 5

2

删除所有与流程相关的东西并尝试Directory.GetDirectories ()Directory.GetFiles()方法:

public IEnumerable<string> GetAllFiles(string rootDirectory)
{
    foreach(var directory in Directory.GetDirectories(
                                            rootDirectory, 
                                            "*", 
                                            SearchOption.AllDirectories))
    {
        foreach(var file in Directory.GetFiles(directory))
        {
            yield return file;
        }
    }
}

来自 MSDN,SearchOption.AllDirectories:

在搜索操作中包括当前目录和所有子目录。此选项包括重新解析点,例如搜索中的已安装驱动器和符号链接。

于 2011-09-29T11:41:32.080 回答
1

在每个目录的循环中使用肯定会更快,DirectoryInfo.GetFiles而不是产生大量新进程来读取它们的输出。

于 2011-09-29T11:43:38.823 回答
1

对于数百万个文件,您实际上会遇到文件系统限制(请参阅内容并搜索“300,000”),因此请考虑到这一点。

至于优化,我认为你真的想懒惰地迭代,所以你必须 P/Invoke 进入FindFirstFile/ FindNextFile

于 2011-09-29T11:44:56.727 回答
0

假设您的数百万个文件分布在多个子目录中并且您使用的是 .NET 4.0,您可以查看并行扩展。

使用并行 foreach 循环来处理子目录列表,可以使事情变得更快。

与在较低级别尝试多线程相比,新的并行扩展也更安全、更易于使用。

要注意的一件事是确保将并发进程的数量限制在合理的范围内。

于 2011-09-29T11:51:01.303 回答
0

检查已经可用的Directory.GetFiles重载。
例如:

var paths = Directory.GetFiles(root, "*", SearchOption.AllDirectories);

是的,这将需要很多时间。但我认为您不能仅使用 .Net 类来提高其性能。

于 2011-09-29T11:41:31.070 回答