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

プロファイラーを使用して、どの操作が最も遅いかを調べます。それからどうすれば速くなるかを考えます。そうしないと、何かを最適化して時間を無駄にする可能性がありますが、それはボトルネックではなく、期待される速度向上をもたらしません。

あなたの場合、この関数を初めて呼び出すとき (ディレクトリ構造がキャッシュにないとき)、ほとんどの時間が GetDirectories() および GetFiles() 関数に費やされることに気付くでしょう。すべてのファイルのリストをメモリ (またはデータベース) に事前にキャッシュし、FileSystemWatcher を使用してファイル システムの変更を監視し、ファイル リストを新しいファイルで更新することができます。または、Windows インデックス サービスなどの既存のサービスを使用することもできますが、これらはすべてのコンピューターで利用できるとは限りません。

2 つ目のボトルネックは、ListBox へのファイルの追加です。追加されたアイテムの数が多い場合は、 ListBox.BeginUpdate を使用してリストボックスの描画を一時的に無効にし、終了したらListBox.EndUpdateを使用して再度有効にすることができます。これにより、場合によっては大幅なスピードアップが可能になります。

于 2012-04-13T21:58:11.783 に答える
1

答えは通常、オペレーティング システムによって異なります。いずれにせよ、独自のファイル データベースを構築して維持する必要があります。あなたの例のような明示的な検索は、コストがかかりすぎて遅くなります。

Linux (および、私が間違っていなければ Mac OS X) での標準的な解決策は、定期的にシステムによって更新される、locatedbファイルを維持することです。これらのシステムで実行すると、プログラムはこのデータベースに対してクエリを実行できます。

于 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

およびクラスがファイル システムから追加情報を取得するため、 を使用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 に答える
0

すべてのファイルを一度に列挙して、リストを保存できます。

しかし、それができない場合は、基本的にこれで十分です。次の 2 つの小さなことを行うことができます。

  • スレッドを使用してみてください。これは SSD ではかなり改善されますが、回転ディスクでは問題が発生する可能性があります
  • DirectoryInfo.GetFileSystemEntries を使用します。これにより、1 回の効率的な呼び出しでファイルとディレクトリが返されます。
于 2012-04-13T21:28:20.877 に答える