2015-07-30 4 views
4

Я пишу программу для поиска текстовых файлов, где в каждой строке есть определенная строка. Цель состоит в том, чтобы игнорировать все после этой строки. Мой текущий код читает весь текстовый файл и возвращает Enumerable из результирующих имен файлов, где был найден термин.Поиск в текстовых файлах до определенной строки

var searchResults = files.Where(file => File.ReadAllText(file.FullName).Contains(searchTerm)).Select(file => file.FullName); 

Можно ли включить игнорирование всех строк после этой конкретной строки? Эффективность будет важна, так как есть тысячи файлов.

+0

Вы хотите вернуть строки (до найденной строки поиска) вместо имен файлов? Как взвесить эти файлы? Производительность может быть критически чистой в огромных текстовых файлах. –

ответ

7

Вы можете изменить свой запрос:

var searchResults = files.Where(file => File.ReadLines(file.FullName).Any(line => line.Contains(searchTerm)) 
         .Select(file => file.FullName)); 

Вместо использования File.ReadAllText вы можете использовать File.ReadLines который лениво-оценку и следует прекратить чтение, если условие выполняется.

https://msdn.microsoft.com/en-us/library/vstudio/dd383503(v=vs.100).aspx

Чтобы сделать это быстрее, вы можете также использовать параллельный LINQ:

var searchResults = files.AsParallel() 
         .Where(file => File.ReadLines(file.FullName).Any(line => line.Contains(searchTerm)) 
         .Select(file => file.FullName)); 
1

Вы можете прочитать файл построчно и закрыть его, если значение найдено:

static string[] SearchFiles(string[] filesSrc, string searchTerm) 
    { 
     List<string> result = new List<string>(); 
     string line = ""; 
     StreamReader reader = null; 

      for (int i = 0; i < filesSrc.Length; i++) 
      { 
       reader = new StreamReader(filesSrc[i]); 
       while ((line = reader.ReadLine()) != null) 
        if (line.Contains(searchTerm)) { result.Add(filesSrc[i]); break; } 
      } 

     reader.Dispose(); 

     return result.ToArray(); 
    } 

И используйте его как: string[] files = SearchFiles(yourfiles[], "searchTerm");

В зависимости от того, вам нужно передать File[] этому методу, а затем получить строковое значение с полным путем, но вы не представили пример своего класса File, и его трудно реализовать, не зная, как выглядит ваш класс.

P.S. Использование LINQ - еще одно возможное решение и хорошее (не говоря уже о том, что это всего лишь 1-2 строки кода).

Импровизированный performance test показал, что в этом случае LINQ на 10-20% медленнее, поэтому, вероятно, лучше придерживаться его.

Смежные вопросы