2009-05-05 2 views
5

Я использую C# (.Net 2.0), и у меня есть довольно большой текстовый файл (в среднем около 1600 строк), который мне нужно периодически проверять убедитесь, что имеется определенная строка текста.Самый эффективный способ убедиться, что строка существует в текстовом файле

Каков наиболее эффективный способ сделать это? Нужно ли мне каждый раз загружать весь файл в память?

Есть ли api-файл для поиска файлов, который я мог бы использовать?

Спасибо за любую помощь/совет.

ответ

5

Ну, вы всегда можете использовать FileSystemWatcher, чтобы дать вам событие, когда файл был изменен, таким образом вы только сканируете файл по требованию.

+1

Хорошая идея. Мы делаем это в одном проекте, и все же я все еще забываю об этом. –

+0

Очень приятно! Я думаю, что, вероятно, буду использовать этот подход. –

+0

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

3

Если строка текста всегда будет одинаковой, то использование RegEx в соответствии с текстом строки, вероятно, более эффективно, чем переключение по файлу в соответствии с текстом с помощью String.Equals() или ==.

Это говорит о том, что я не знаю, так или иначе, в C#, чтобы найти текст в файле, не открывая файл в память и не читая строки.

Это link является хорошим руководством по использованию RegEx для соответствия строк в файле с использованием C#.

+0

Также - это, вероятно, очевидно, но с использованием RegEx линия не всегда должна быть точно такой же, она просто должна следовать распознаваемому шаблону. –

+0

Возможно, мне что-то не хватает. Использует ли RegEx в каждой строке более эффективно, чем String.Contains(), String.StartsWith() или любой другой встроенный синтаксический анализатор строк? У меня нет сложного шаблона. Я ищу точную строку. –

+0

Мое предположение искало образец текста. –

1

Вы должны быть в состоянии просто цикл по линиям, как это:

String line; 
while ((line = file.ReadLine()) != null) 
{ 
    if (line matches regex blah) 
     return true; 
} 
return false; 

Метод ReadLine загружает только одну строку файла в память, а не весь файл. Когда цикл запускается снова, единственная ссылка на эту строку будет потеряна, и, таким образом, линия будет собираться мусором, когда это необходимо.

+0

Спасибо. Это тоже помогает. –

2

Это действительно зависит от вашего определения «эффективный».

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

Если вы имеете в виду в кратчайшие сроки, то это задача, которая принесет большие выгоды от параллельной архитектуры. Разделите файл на куски и передайте каждый кусок в другой поток для обработки. Конечно, это не особенно эффективный процессор, так как он может использовать все ваши ядра на высоком уровне использования.

Если вы хотите просто выполнить минимальное количество работ, есть ли что-нибудь, что вы уже знаете о файле? Как часто он будет обновляться? Являются ли первые 10 символов каждой строки одинаковыми? Если вы просмотрели 100 строк в последний раз, вам нужно снова просмотреть эти строки? Любой из них может создать огромную экономию как для использования времени, так и для памяти.

В конце дня, хотя нет волшебной пули, и для поиска файла (в худшем случае) используется операция O (n).


К сожалению, просто перечитать, что и он может встретить как саркастический, и я не имею в виду, что это будет. Я просто хотел подчеркнуть, что любые выигрыши, которые вы делаете в одной области, скорее всего, будут терять в другом месте, а «эффективный» - очень двусмысленный термин в подобных обстоятельствах.

+0

К сожалению, файл * может * сильно варьироваться, но большинство будет почти идентичным. И местоположение линии, которую я ищу, почти наверняка будет в другом месте каждый раз. –

+1

В таких случаях может быть полезно предположить, что файл почти идентичен и обрабатывает его таким образом (например, начните поиск, где линия была ранее и излучалась).Вы можете сделать ваш худший случай медленнее, поскольку вы больше не читаете файл линейно, но если вы редко попадаете в худший случай, тогда общая система работает быстрее. –

3

Если они не очень длинны, то в современных вычислительных терминах 1600 строк не много!Файл IO будет обрабатываться средой выполнения и будет буферизован и будет поразительно быстр, а объем памяти поразительно ничем не примечателен.

Просто прочитайте файл по строкам или используйте System.IO.File.ReadAllLines(), а затем посмотрите, существует ли линия, например. используя сравнение всей строки со строкой.

Это не будет вашим узким местом.

Ваше узкое место может возникнуть, если вы часто проводите опрос и/или используете регулярные выражения без необходимости. Лучше всего использовать наблюдатель файловой системы, чтобы избежать разбора файла вообще, если он не изменился.

2
List<String> lines = System.IO.File.ReadAllLines(file).ToList() 
lines.Contains("foo"); 
+0

yeap, легко понять, я утверждаю, что это не узкое место, он получает мое преимущество. ps: «Containts»? – Will

+0

написал это с моей головы. извините за эту опечатку. –

+0

ToList() - это сборка .Net 3.5. Мне нужно решение 2.0. –

0

Я бы объединить несколько методов, используемых здесь:

1). Установите файл FileSystemWatcher в файл. Установите необходимые фильтры для предотвращения ложных срабатываний. Вы не хотите проверять файл без необходимости.

2). Когда FSW вызывает событие, захватите содержимое, используя строку fileString = File.ReadAllLines().

3). Используйте простое регулярное выражение, чтобы найти соответствие для вашей строки.

4). Если совпадение имеет индекс больше, чем -1, то файл содержит строку в любом значении в индексе.

Вы успешно избегали разбора файла по строкам, у вас есть, который потенциально загружает большое количество данных (хотя 1600 строк текста вряд ли так велико) в память. Когда строковый литерал выходит за пределы области видимости, он будет возвращен сборщиком мусора.

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