2010-10-21 5 views
6

У меня есть текстовый файл, содержащий 21000 строк (по одной строке) и 500 МБ других текстовых файлов (maily исходники). Для каждой строки мне нужно определить, содержится ли она в любом из этих файлов. Я написал программу, которая выполняет эту работу, но ее производительность ужасна (это сделало бы это через пару дней, мне нужно проделать эту работу максимум в 5-6 часов).
Я пишу с помощью C#, Visual Studio 2010Поиск нескольких строк в нескольких файлах

У меня есть несколько вопросов по поводу моей проблемы:
а) Какой подход лучше?

foreach(string s in StringsToSearch) 
{ 
    //scan all files and break when string is found 
} 

или

foreach(string f in Files) 
{ 
    //search that file for each string that is not already found 
} 

б) Лучше ли сканировать один файл построчно

StreamReader r = new StreamReader(file); 
while(!r.EndOfStream) 
{ 
    string s = r.ReadLine(); 
    //... if(s.Contains(xxx)); 
} 

или

StreamReader r = new StreamReader(file); 
string s = r.ReadToEnd(); 
//if(s.Contains(xxx)); 

с) резьб бы повысить производительность и как сделать это?
d) Есть ли программное обеспечение, которое может это сделать, поэтому мне не нужно писать собственный код?

+0

вы должны написать программу? windows имеет встроенный findstr. Вы можете использовать цикл for, который мог бы искать эти другие файлы параллельно. –

+0

Определенно не правильный/полный ответ, но не загружать все (500 МБ!) файлы для каждой строки. После того, как у вас есть (часть) файла в памяти, выполните все ваши действия. – Bertvan

+0

Я хочу загрузить весь файл один за другим, а не 500 МБ файлов одновременно. – Ichibann

ответ

3

Вы хотите минимизировать ввод/вывод файлов, поэтому ваша первая идея очень плоха, потому что вы открываете «другие» файлы до 21 000 раз. Вы хотите использовать что-то на основе второго (a1). И когда эти другие файлы не слишком большие, загрузите их в память один раз с помощью readAllText.

List<string> keys = ...; // load all strings 

foreach(string f in Files) 
{ 
    //search for each string that is not already found 
    string text = System.IO.File.ReadAllText(f); //easy version of ReadToEnd 


    // brute force 
    foreach(string key in keyes) 
    { 
     if (text.IndexOf(key) >= 0) .... 
    } 

} 

Часть грубой силы может быть улучшена, но я думаю, вы найдете ее приемлемой.

+0

Есть ли (text.IndexOf (key)> = 0) быстрее, чем if (text.Contains (key))? – Ichibann

+0

@Ichi: Нет, я бы ожидал, что они будут одинаково быстрыми. –

2
  1. В обоих а) и б), второй вариант является эффективным
  2. нарезание резьбы не может улучшить производительность COz каждого потока будет читать файл с вашего диска, так что диск станет узким местом.
  3. СРЮ я понятия не имею, о с/ш для вашей цели

нить фрагмент

 foreach (FileInfo file in FileList) 
     { 
     Thread t = new Thread(new ParameterizedThreadStart(ProcessFileData)); 
     t.Start(file.FullName); 
     }//where processFileData is the method that process the files 

Общие рекомендации I/O

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

  1. минимизировать количество файлов операции вы выполняете
  2. Group несколько трансферов небольшой I/O в один большой трансфер.Один пишет восемь страниц быстрее, чем восемь отдельных одностраничных записей, в первую очередь потому, что он позволяет жесткому диску записать данные за один проход по поверхности диска. Дополнительная информация информация,
  3. Выполнение последовательных чтений вместо поиск и чтение небольших блоков данных. Ядро прозрачно операций ввода-вывода кластеров, что делает последовательные чтения намного быстрее.
  4. Избегайте пропускания вперед в пустой файл перед записью данных. Система должна записывать нули в промежуточное пространство , чтобы заполнить пробел. Для получения дополнительной информации см. Чтение , как правило, дешевле, чем запись данных.
  5. Отложите любые операции ввода-вывода до . Укажите, что ваше приложение действительно нуждается в данных.
  6. Используйте систему преференций для захвата только пользовательских настроек (такой как окна позиций и зрение настройки), а не данные, которые могут быть недорого пересчитываются.
  7. Не предполагайте, что данные кэширования файлов в памяти ускорят ваше приложение . Хранение данных файла в памяти улучшает скорость до тех пор, пока память не выйдет на диск, на , на которой вы платите цену за , обращаясь к диску еще раз. Стремится найти подходящий баланс между чтением с диска и кэширования в памяти
6

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

grep -f strings-file other-files... 

должен сделать трюк. Я уверен, что там есть реализация Windows. В худшем случае Cygwin получит его.

EDIT: Это ответ на вопрос d)

+0

Да, несмотря на тег [C#], это лучший подход. –

+0

Я не знаком с grep и как это работает, может быть, мало поможет, как это использовать? – Ichibann

+0

Grep - очень распространенный инструмент в системах * nix. Там есть много документации, поэтому где-то есть хороший учебник. Предлагаемая команда ищет все строки, найденные в «string-file» в любом из «других файлов», и выводит все соответствующие строки в «other-files». Существует много вариантов изменения вывода на то, что вам нужно. –

2

ли поиск должен быть в режиме реального времени на нынешних 500 Мб текста? Причина, по которой я спрашиваю, заключается в том, что вы можете создать индекс поиска в текстовых файлах и выполнить поиск. Было бы гораздо быстрее ... Посмотрите на Lucene

Lucene.Net

C# and Lucene to index and search

+0

Это не обязательно поиск в режиме реального времени. Это одноразовая задача. Забудьте об этом: P – Ichibann

+0

Затем используйте Lucene (я не использовал Windows Search SDK), чтобы создать полный индекс поиска и выполнить поиск по нему ... Я использовал Lucene раньше ... Это быстро! – zam6ak

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