2013-02-12 4 views
13

Мне нужно найти строку, примерно 13 символов, в группе текстовых файлов с использованием C#. Количество текстовых файлов меняется и может варьироваться от 100 до 1000. Размер файлов может варьироваться от 1 КБ до 10 МБ.Более быстрый способ поиска строки в текстовых файлах

Я пробовал наивный способ открытия каждого файла, читать его по строкам и посмотреть, существует ли строка (с помощью index.of), но это слишком медленно. Я также попытался использовать алгоритм Boyer-Moore, который улучшил время, на 5 секунд, но все же это кажется медленным.

Любая идея о том, как ускорить поиск?

+2

Ваше замедление, вероятно, происходит от чтения файлов по строкам. Прочитайте файл сразу в памяти и выполните поиск. – dda

+0

http://stackoverflow.com/questions/4289353/fastest-way-to-search-ascii-files-in-c-sharp-for-simple-keywords – Ofiris

+0

Вам нужно выполнить поиск по тем же файлам несколько раз? – user626528

ответ

3

Вам следует рассмотреть возможность использования поиска в операционной системе с содержимым. Взгляните на Microsoft Windows Search 3.x SDK

Или вы можете использовать PLINQ для поиска в массиве файлов. Смотрите эту ссылку:

File Content and Directory Search using Directory.GetFiles and PLINQ

+1

Не вниз, но я могу это понять: вы просто делаете глупое решение (в основном IndexOf) параллельно PLINQ, что не делает его хорошим решением - вы в основном просто бросаете на него больше аппаратных средств, тем самым делая это Быстрее. Это как сказать парню, чтобы он читал и обрабатывал свои файлы в нескольких потоках. Использование боярского мура, как он предлагает, намного лучше этого. Также я не уверен, поддерживает ли MS Search пользовательскую токенизацию, которая, как представляется, является требованием. Итак, на мой взгляд, как эксперт по поиску, здесь гораздо лучшие ответы, чем ваши. Извини ... Я ценю добрые намерения. – atlaste

+0

Блестящий! что PLINQ - фааст! и всего пару строк! Вместо этого я использовал ReadAllText, и это самый быстрый. –

3

Два вариант приходит на ум:

Чтения текстового файла в памяти и просто искать всю строку сразу.

Если это окажется слишком медленным или слишком голодным, используйте указатель типа Apache Lucene. Существует хороший и простой SDK для этого доступны для .NET, называется Lucene.net

Вот небольшое введение для него: http://www.codeproject.com/Articles/29755/Introducing-Lucene-Net

1

Если ваш компьютер может справиться с этим попробуйте загрузить все текстовые файлы в памяти (используя technique shown here, а затем оценивать текст в памяти.

Если вы не можете обрабатывать все файлы за один раз, сделайте это для самых маленьких файлов. Файл I/O будет вашим самым большим расходом здесь, поэтому вы хотите чтобы максимально свести к минимуму это.

8

В зависимости от ho w много раз вы хотите сделать «поиск», вы хотите использовать поисковую систему или нет. Если вы хотите много раз искать, используйте поисковую систему, иначе: нет. Я расскажу, как реализовать оба сценария здесь.

При использовании поисковой системы: похоже, что вы ищете подстроки, а это значит, что вы должны индексировать свои файлы как таковые, используя свою любимую поисковую систему, предпочтительно такую, которую вы можете настроить (lucene, terrier и т. Д.). Техника, в которой вы нуждаетесь, - это индексирование триграмм, то есть: все 3-значные комбинации должны быть проиндексированы. F.ex .: «foobar» будет генерировать «foo», «oob», «oba» и «bar». При поиске вы хотите сделать то же самое с вашим запросом и выдать запрос поисковой системы с И всех этих триграмм. (Это приведет к объединению в списках проводки из документов, которые вернут их идентификаторы или все, что вы разместите в списках проводки).

В качестве альтернативы вы можете реализовать массивы суффиксов и индексировать свои файлы один раз. Это даст немного большую гибкость, если вы хотите найти короткие (1-2 символа) подстроки, но с точки зрения индексов сложнее поддерживать. (Есть несколько исследований в CWI/Amsterdam для быстрых индексирующих массивов суффикса)

Если вы хотите искать только несколько раз, то использовать алгоритм Boyer-Moore (я обычно использую Boyer-moore-sunday, как описано в [Graham A. Stephen, String Search]) или скомпилированный DFA (вы можете создать их из NFA, что проще сделать). Тем не менее, это только даст вам небольшое увеличение скорости по той простой причине, что диск IO, вероятно, является вашим узким местом и сравнивает кучу байтов, которые нужно декодировать в любом случае, довольно быстро.

Самое большое улучшение, которое вы можете сделать, это не чтение вашего файла по строкам, а в блоках. Вы должны настроить NTFS на использование размера блока в 64 КБ, если сможете, и читать файлы в размножении 64 КБ - считайте 4 МБ или более в одном чтении. Я бы даже предложил использовать асинхронный ввод-вывод, чтобы вы могли одновременно читать и обрабатывать (ранее прочитанные данные). Если вы сделаете это правильно, это уже должно дать вам реализацию с разделенной секунды для 10 МБ на большинстве современных аппаратных средств.

И последнее, но не менее важное: аккуратный трюк, используемый для получения информации, также предназначен для сжатия ваших данных с использованием алгоритма быстрого сжатия. Поскольку диск IO медленнее операций с памятью/процессором, это, вероятно, также поможет. Компрессор Snappy от Google - хороший пример быстрого алгоритма сжатия.

1

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

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