多くのブログや記事を参照した後、フォルダー内のすべてのファイルで文字列を検索する次のコードに到達しました。私のテストではうまく機能しています。
[〜#〜] questions [〜#〜]
注:非常に小さなファイルでテストしました。また、非常に少数のファイル。
[〜#〜] code [〜#〜]
static void Main()
{
string sourceFolder = @"C:\Test";
string searchWord = ".class1";
List<string> allFiles = new List<string>();
AddFileNamesToList(sourceFolder, allFiles);
foreach (string fileName in allFiles)
{
string contents = File.ReadAllText(fileName);
if (contents.Contains(searchWord))
{
Console.WriteLine(fileName);
}
}
Console.WriteLine(" ");
System.Console.ReadKey();
}
public static void AddFileNamesToList(string sourceDir, List<string> allFiles)
{
string[] fileEntries = Directory.GetFiles(sourceDir);
foreach (string fileName in fileEntries)
{
allFiles.Add(fileName);
}
//Recursion
string[] subdirectoryEntries = Directory.GetDirectories(sourceDir);
foreach (string item in subdirectoryEntries)
{
// Avoid "reparse points"
if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
{
AddFileNamesToList(item, allFiles);
}
}
}
[〜#〜] reference [〜#〜]
File.ReadAllText()の代わりに使用する方が良い
File.ReadLines(@"C:\file.txt");
IEnumerable
(yielded)を返すので、テキストファイルの最終行に到達する前に文字列が見つかった場合、ファイル全体を読み取る必要はありません。
私は非常に似たようなものを書きました。いくつかの変更をお勧めします。
私はバイナリ検索ツールを作成していました。ここに、私があなたに手を差し伸べるために書いたもののスニペットがあります
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Parallel.ForEach(Directory.EnumerateFiles(_folder, _filter, SearchOption.AllDirectories), Search);
}
//_array contains the binary pattern I am searching for.
private void Search(string filePath)
{
if (Contains(filePath, _array))
{
//filePath points at a match.
}
}
private static bool Contains(string path, byte[] search)
{
//I am doing ReadAllBytes due to the fact that I am doing a binary search not a text search
// There are no "Lines" to seperate out on.
var file = File.ReadAllBytes(path);
var result = Parallel.For(0, file.Length - search.Length, (i, loopState) =>
{
if (file[i] == search[0])
{
byte[] localCache = new byte[search.Length];
Array.Copy(file, i, localCache, 0, search.Length);
if (Enumerable.SequenceEqual(localCache, search))
loopState.Stop();
}
});
return result.IsCompleted == false;
}
これは、2つのネストされた並列ループを使用します。この設計はひどく非効率的であり、 Booyer-Moore検索アルゴリズムを使用することで大幅に改善できますが 、バイナリ実装を見つけることができず、作成する時間がありませんでしたもともと自分で実装するために。
ここでの主な問題は、すべてのファイルをすべての検索でリアルタイムで検索していることです。 2人以上のユーザーが同時に検索している場合、ファイルアクセスの競合の可能性もあります。
パフォーマンスを劇的に向上させるために、事前にファイルのインデックスを作成し、ファイルが編集/保存されるときにインデックスを作成します。 lucene.net のようなものを使用してインデックスを保存し、インデックスをクエリし(再び luence.net を使用)、ファイル名をユーザーに返します。そのため、ユーザーはファイルを直接照会しません。
このリンクをたどると SO Post インデックス作成の実装に有利なスタートを切るかもしれません。リンクをたどりませんでしたが、一見の価値があります。
ちょっと頭を上げて、これはあなたの現在のアプローチからの激しいシフトであり、
Contains
の代わりに、アルゴリズムBoyer-Moore検索を使用する方が適切です。
失敗シナリオ:ファイルに読み取り許可がありません。
permission to open a file
がない場合、コードは例外で失敗すると思います。
次のコードと比較してください。 http://bgrep.codeplex.com/releases/view/36186
後者のコードはサポートしています
-おそらく考慮すべきこと。