Поиск в неупорядоченном лог-файле - PullRequest
2 голосов
/ 31 августа 2011

Где я работаю, у нас есть файл журнала, который содержит такие строки:

31201007061308000000161639030001

Что следует читать так:

31 | год (4) | месяц (4) | день (2) | час (2) | мин (2) | 000000 | объект (3) | пропуск (5) | 0001

Так что для каждой записи должна быть строка, но бывает что-то вроде этого:

31201007192000000000161206930004
31201007192001000000161353900004
31201031201007192004000000161204690004
31201007192004000000090140470004
31201007192005000000090148140004
3120100719200500031201007191515000000161597180001
31201007191700000000161203490001
31201007191700000000161203490001
31201007191700000000161202830001
31201007191700000000

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

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

//Starts Reader
StreamReader reader = new StreamReader(path);
string fileLine = reader.ReadLine();
while (!reader.EndOfStream)
{
  //Regex Matcher
  Regex rx = new Regex(@"31\d\d\d\d\d\d\d\d\d\d\d\d000000161\d\d\d\d\d0001");

  //Looks for all valid lines
  MatchCollection matches = rx.Matches(fileLine);

  //Compares each match against what we are looking for
  foreach (Match m in matches)
  {
    string s = m.Value;
    compareLine(date, badge, s);
  }

  reader.ReadLine();
}
reader.Close(); //Closes reader

У меня такой вопрос: какой хороший способ поиска по файлу? Стоит ли сначала заказать / почистить?

Ответы [ 2 ]

2 голосов
/ 31 августа 2011

Возможно, вам лучше всего выполнить следующие шаги:

  • Разбор каждой строки в объект. Структура должна соответствовать этим строкам. Включите объект DateTime, а также любые другие связанные поля. Это можно легко сделать с помощью Regex, если немного почистить. Используйте группы захвата и повторители. В течение года вы можете использовать (\d{4}), чтобы получить 4 числа подряд вместо \d\d\d\d.
  • Создайте List<MyStruct>, который содержит каждую строку как объект.
  • Используйте LINQ для поиска в списке, например:

    var searchResults = from eachEntry in MyList
                        where eachEntry.Date > DateTime.Now
                        and eachEntry.facility.Contains("003")
                        select eachEntry;

Кроме того, добавьте эту строку в свое регулярное выражение, оно ускорит его, хотя бы на несколько миллисекунд:

MatchCollection matches = rx.Matches(fileLine, RegexOptions.Compiled);
0 голосов
/ 30 апреля 2014

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

string expectedValue = getExpectedValue(date, badge);
// expectedValue = "31201007192000000000161206930004"
foreach (string line in lines)
{
    if (line.IndexOf(expectedValue) >= 0)
    {
          // record found
    }
}

Если вас интересует, содержит ли файл ваш идентификатор или нет, вы можете прочитать весь файл в одну строку и выполнить поиск по

string completeFile = GetFileContents(file);
if (completeFile.IndexOf(expectedValue) >= 0)
{
     // record found
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...