0

Web ページから渡された文字列について、指定されたディレクトリとサブディレクトリの下にあるすべてのファイルをチェックするコードを作成しようとしています。今のところ、私はこのコードを持っています:

    private void ProcessDirectory(string targetDirectory, string origDirectory, string ObjectName)
    {
        string[] fileEntries = Directory.GetFiles(targetDirectory);
        string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);

        foreach (string fileName in fileEntries)
        {
            ProcessFile(fileName, origDirectory, ObjectName);
        }

        foreach (string subdirectory in subdirectoryEntries)
           ProcessDirectory(subdirectory, origDirectory, ObjectName);
    }

    private void ProcessFile(string path, string origDirectory, string ObjectName)
    {
        if (ObjectName != "")
        {
            var fileLines = File.ReadAllLines(path);
            List<string> fileItems = new List<string>(fileLines);

            if (fileItems.Contains(ObjectName))
            {
                string sExt = Path.GetExtension(path).ToLower();

                if (sExt == ".txt")
                {
                    listTextFiles.Items.Add(path.Replace(origDirectory, ""));
                }
            } 
          }

動作しますが、問題は、ファイル内の完全な単語しか検索しないことです。たとえば、「Account」という単語を探し、ファイルに「Account」という単語が含まれている場合、コードは機能します。ファイルに「AccountCode」という単語が含まれている場合、検索で見つかりません。それを修正する方法はありますか?

もう1つの質問は、プロセスの最後に、指定されたディレクトリとすべてのサブディレクトリの下でチェックされたファイルの数を示すカウンターを追加する方法です。

4

4 に答える 4

3

これは非常に回りくどい方法です。ファイルの内容全体をロードして使用するだけIndexOfです:

var content = File.ReadAllText(path);

if (content.IndexOf(ObjectName) > -1) {
    // rest of your code here
}

行ごとにロードし、それらの行でまったく新しいリストを初期化し、各行をチェックする必要はありません。

あなたが尋ねたように、これは部分的な検索の利点ももたらします。

消費しているメモリの量を注意深く監査することで、おそらくこれを大幅に改善できます。あなたの方法と私がここで提供した方法の両方が、条件付きチェックの後で役に立たなくなるためだけに、大きなメモリブロックを割り当てる可能性があります。StringBuilderを使用し、各ファイルで再利用することを検討してください。

于 2013-11-13T23:54:11.863 に答える
1

if fileItems.Contains(ObjectName))条件でリストを検索しfileItemsます:そのリストに と等しい項目が含まれている場合 ObjectName

あなたはおそらく望むでしょう:そのリストに含まれるアイテムが含まれ ObjectNameている場合。したがって、次のように変更します。

if (fileItems.Any(e => e.Contains(ObjectName)))
于 2013-11-13T23:53:50.033 に答える
0

2番目の質問に答えるために。ここでは再帰を使用するため、プロパティまたはクラス レベルの変数を宣言し、ProcessFile メソッドでそれをインクリメントする必要があります。

public int NumberOfMatches { get; set; }

ProcessFile...
{
 if (fileItems.Contains(ObjectName))
 {
      NumberOfMatches++;
 }

補足として、ここで再帰を使用する理由はありません。単一の呼び出しですべてのファイルを取得できます。

string[] allFiles = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);

パフォーマンスが問題になる場合は、マルチスレッドも検討できます。

   Parallel.ForEach(allFiles,
        new ParallelOptions { MaxDegreeOfParallelism = 4 },
        allFiles =>
        {
            ...
        }
于 2013-11-14T01:05:55.643 に答える
0

文字列の内容をチェックするときは、文字列の比較子を実装することを忘れないでください

If(string.Contains( value ,StringComparer.CurrentCultureIgnoreCase ))

// Apply logic...

放置されることが多いです…

于 2013-11-14T01:12:22.630 に答える