在.NET中列出所有文件+目录的最快方法

时间:2009-11-21 16:55:48

标签: .net filesystems

我知道如何使用DirectoryInfo.GetFiles(),但我不认为这是最快的方法。这些“FileInfo”对象看起来有点大......

为什么需要它?好吧,我试图用WDS实现我的搜索工具,但我放弃了。 OleDB连接是可怕的,奇怪的错误,没有任何解释。所以我要做的是:

在SQL2008中重建文件索引。

目前有一些要点需要检查,主要是关于维护:

  1. 如何将所有文件存入数据库
  2. 如何让数据库保持同步 文件系统
  3. 我将尝试稍后FileSystemWatcher需要多少资源,现在我正在寻找从驱动器获取所有文件的最快方法,完整路径为字符串就足够了。

    所以,假设我给你这个:

    List<string> allFiles =
    

    你会如何快速填写它:-) 顺便说一句

    new FileInfo("D:").GetFiles("*",SearchOption.All)
    
    我想,

    不是最好的方式。原因1,可能的开销。更严重的原因2:在无法访问路径的情况下抛出(这肯定会在1.5 Mio文件之后发生)..

3 个答案:

答案 0 :(得分:1)

我为每个子目录启动一个单独的线程,并使用wait对象限制线程。这样我通过将文件名发送到数据库(或文件,如果你想要的话)来保持可管理的内存大小,并通过让几个线程完成工作来加快速度。

答案 1 :(得分:1)

看一下this question,它有几种替代方法以递归方式递归获取文件,从而大大减少了开销。

答案 2 :(得分:0)

这个怎么样?它使用ThreadPool和递归。将输出直接发送到数据库的过程耗时太长,但我认为一旦将其输入文件,您就可以找到一种有效的方法将其输入数据库(如果需要)。

...输出

56337/379104 - (number directories/files)
Elapsed seconds: 13.0

...代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data.SqlClient;
using System.IO;

namespace FileCacher
{
    class Program
    {
        public static void Main()
        {
            try
            {
                CacheFiles();
            }
            finally
            {
                Console.WriteLine();
                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
            }
        }

        private static List<string> sFiles = new List<string>();
        private static void AddFiles(params string[] files)
        {
            lock (sFiles)
            {
                sFiles.AddRange(files);
            }
        }

        private static List<string> sDirectories = new List<string>();
        private static void AddDirectories(params string[] dirs)
        {
            lock (sDirectories)
            {
                sDirectories.AddRange(dirs);
            }
        }

        private static void CacheFiles()
        {
            AddDirectories(@"C:\");
            CacheDirectory(@"C:\");

            var numFiles = 0;
            var numDirs = 0;
            while (true)
            {
                Thread.Sleep(1000);
                var newNumDirs = sDirectories.Count;
                var newNumFiles = sFiles.Count;
                if (newNumDirs == numDirs && newNumFiles == numFiles)
                {
                    Console.WriteLine();
                    break;
                }
                numDirs = newNumDirs;
                numFiles = newNumFiles;
                Console.CursorLeft = 0;
                Console.Write(string.Format("{0}/{1}", numDirs, numFiles));
            }

            using (var fs = new FileStream(@"C:\garb\Dirs.txt", FileMode.Create, FileAccess.Write))
            {
                var sw = new StreamWriter(fs);
                sDirectories.Sort();
                foreach (var dir in sDirectories)
                    sw.WriteLine(dir);
            }

            using (var fs = new FileStream(@"C:\garb\Files.txt", FileMode.Create, FileAccess.Write))
            {
                var sw = new StreamWriter(fs);
                sFiles.Sort();
                foreach (var file in sFiles)
                    sw.WriteLine(file);
            }
        }

        private static void CacheDirectory(object dir)
        {
            try
            {
                var dirPath = (string)dir;
                var dirs = Directory.GetDirectories(dirPath);

                AddDirectories(dirs);
                AddFiles(Directory.GetFiles(dirPath));

                foreach (var childDir in dirs)
                    ThreadPool.QueueUserWorkItem(new WaitCallback(CacheDirectory), childDir);
            }
            catch (UnauthorizedAccessException)
            {
                //ignore
            }
        }

    }
}