Самый эффективный способ убедиться, что строка существует в текстовом файле - PullRequest
5 голосов
/ 05 мая 2009

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

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

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

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

Ответы [ 7 ]

5 голосов
/ 05 мая 2009

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

3 голосов
/ 05 мая 2009

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

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

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

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

3 голосов
/ 05 мая 2009

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

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

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

2 голосов
/ 05 мая 2009
List<String> lines = System.IO.File.ReadAllLines(file).ToList()
lines.Contains("foo");
2 голосов
/ 05 мая 2009

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

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

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

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

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


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

1 голос
/ 05 мая 2009

Вы должны иметь возможность просто циклически проходить по следующим строкам:

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

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

0 голосов
/ 05 мая 2009

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...