Après avoir référé de nombreux blogs et articles, j'ai atteint le code suivant pour rechercher une chaîne dans tous les fichiers d'un dossier. Cela fonctionne bien dans mes tests.
[~ # ~] questions [~ # ~]
Remarque: j'ai testé avec de très petits fichiers. Aussi très peu de fichiers.
[~ # ~] 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);
}
}
}
[~ # ~] référence [~ # ~]
Au lieu de File.ReadAllText () mieux utiliser
File.ReadLines(@"C:\file.txt");
Il retourne IEnumerable
(cédé) donc vous n'aurez pas à lire le fichier entier si votre chaîne est trouvée avant que la dernière ligne du fichier texte soit atteinte
J'ai écrit quelque chose de très similaire, quelques changements que je recommanderais.
Je créais un outil de recherche binaire, voici quelques extraits de ce que j'ai écrit pour vous aider
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;
}
Cela utilise deux boucles parallèles imbriquées. Cette conception est terriblement inefficace et pourrait être grandement améliorée en utilisant algorithme de recherche Booyer-Moore mais je n'ai pas pu trouver une implémentation binaire et je n'ai pas eu le temps quand je l'ai écrite à l'origine pour l'implémenter moi-même .
le principal problème ici est que vous recherchez tous les fichiers en temps réel pour chaque recherche. il existe également la possibilité de conflits d'accès aux fichiers si plus de 2 utilisateurs effectuent une recherche en même temps.
pour améliorer considérablement les performances, j'indexerais les fichiers à l'avance, et au fur et à mesure de leur modification/sauvegarde. stocker l'indexé en utilisant quelque chose comme lucene.net puis interroger l'index (à nouveau en utilisant luence.net ) et renvoyer les noms de fichiers à l'utilisateur. afin que l'utilisateur n'interroge jamais directement les fichiers.
si vous suivez les liens dans ce SO Post vous pouvez avoir une longueur d'avance sur la mise en œuvre de l'indexation. Je n'ai pas suivi les liens, mais ça vaut le coup d'oeil.
Attention, ce sera un changement intense par rapport à votre approche actuelle et nécessitera
Au lieu de Contains
mieux utiliser l'algorithme de recherche Boyer-Moore.
Scénario d'échec: le fichier n'a pas l'autorisation de lecture.
Je pense que votre code échouera avec une exception si vous manquez permission to open a file
.
Comparez-le avec le code ici: http://bgrep.codeplex.com/releases/view/36186
Ce dernier code prend en charge
- des choses que vous devriez probablement considérer.