2

我编写了一个程序来查找计算机中的特定文件,但是它在获取计算机上的许多文件时遇到了缓慢和延迟的问题

此功能正在获取所有文件

void Get_Files(DirectoryInfo D)
        {
            FileInfo[] Files;
            try
            {
                Files = D.GetFiles("*.*");
                foreach (FileInfo File_Name in Files)
                    listBox3.Items.Add(File_Name.FullName);
            }
            catch { }

            DirectoryInfo[] Dirs;
            try
            {
                Dirs = D.GetDirectories();
                foreach (DirectoryInfo Dir in Dirs)
                {
                    if (!(Dir.ToString().Equals("$RECYCLE.BIN")) && !(Dir.ToString().Equals("System Volume Information")))
                        Get_Files(Dir);
                }
            }
            catch { }
        }

还有另一种方法可以让所有计算机文件更快一点吗?

4

5 回答 5

2

使用分析器找出最慢的操作。然后考虑如何让它更快。否则你可以通过优化一些东西来浪费你的时间,这不是瓶颈,也不会给你带来预期的加速。

In your case, you will probably find, that when you call this function for the first time (when directory structure is not in cache), most time will be spent in GetDirectories() and GetFiles() functions. You can pre-cache list of all files in memory (or in database) and use FileSystemWatcher to monitor changes in filesystem to update your file list with new files. Or you can use existing services, such as Windows Indexing service, but these may not be available on every computer.

Second bottleneck could be adding files to ListBox. If number of added item is large, you can temporarily disable drawing of listbox using ListBox.BeginUpdate and when you finish, enable it again with ListBox.EndUpdate. This can sometimes lead to huge speed up.

于 2012-04-13T21:58:11.783 回答
1

答案通常取决于您的操作系统。在任何情况下,您都希望建立和维护自己的文件数据库;像您的示例中的显式搜索将太昂贵且太慢。

Linux(和 Mac OS X,如果我没记错的话)上的标准解决方案是维护一个locateb文件,该文件由系统定期更新。如果在这些系统上运行,您的程序可以对该数据库进行查询。

于 2012-04-13T21:25:10.503 回答
1

部分问题是 GetFiles 方法在获取文件夹中的所有文件之前不会返回,并且如果您正在执行递归搜索,那么对于您递归进入的每个子文件夹,它将花费越来越长的时间。

研究使用 DirectoryInfo.EnumerateFile 或 DirectoryInfo.EnumerateFileSystemInfos

从文档:

EnumerateFiles 和 GetFiles 方法的区别如下: 使用 EnumerateFiles 时,可以在返回整个集合之前开始枚举 FileInfo 对象的集合;使用 GetFiles 时,必须等待返回整个 FileInfo 对象数组,然后才能访问该数组。因此,当您处理许多文件和目录时,EnumerateFiles 会更有效。

EnumerateFileSystemInfos 也是如此

您还可以查看查询索引服务(如果它已安装并正在运行)。请参阅 CodeProject 上的这篇文章:

http://www.codeproject.com/Articles/19540/Microsoft-Indexing-Service-How-To

我通过谷歌搜索“如何查询 MS 文件系统索引”找到了这个

于 2012-04-13T21:47:12.497 回答
0

您可以枚举所有文件一次并存储列表。

但如果你不能做到这一点,这基本上是最好的。你可以做两件小事:

  • 尝试使用线程。这在 SSD 上会好很多,但在旋转磁盘上可能会受到伤害
  • 使用 DirectoryInfo.GetFileSystemEntries。这将在一次有效的调用中返回文件和目录。
于 2012-04-13T21:28:20.877 回答
0

您会发现使用和类从文件系统获取额外信息的性能要快得多Directory.GetFiles(),这比简单地返回基于字符串的文件名要慢得多。FileInfoDirectoryInfo

这是一个代码示例,它应该会产生很大改进的结果,并将检索文件的操作从在列表框中显示它们的操作中抽象出来。

static void Main(string[] args)
{
    var fileFinder = new FileFinder(@"c:\SomePath");
    listBox3.Items.Add(fileFinder.Files);
}

/// <summary>
/// SOLID: This class is responsible for recusing a directory to return the list of files, which are 
/// not in an predefined set of folder exclusions.
/// </summary>
internal class FileFinder
{
    private readonly string _rootPath;
    private List<string> _fileNames;
    private readonly IEnumerable<string> _doNotSearchFolders = new[] { "System Volume Information", "$RECYCLE.BIN" };

    internal FileFinder(string rootPath)
    {
        _rootPath = rootPath;
    }

    internal IEnumerable<string> Files
    {
        get
        {
            if (_fileNames == null)
            {
                _fileNames = new List<string>();
                GetFiles(_rootPath);
            }

            return _fileNames;
        }
    }

    private void GetFiles(string path)
    {
        _fileNames.AddRange(Directory.GetFiles("*.*"));

        foreach (var recursivePath in Directory.GetDirectories(path).Where(_doNotSearchFolders.Contains))
        {
            GetFiles(recursivePath);
        }
    }
}
于 2012-04-13T21:31:08.853 回答