2011-01-21 4 views
1

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

Файл журнала находится в формате Категория: Информация

Case Number: CASE01 
User ID: JOSM 
Software: Microsoft Word 
Date Started: 21-01-2010 
Date Ended: 22-01-2010 

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

До сих пор я попытался вставить все это в массив, разделенный на \ r \ n, но мне нужно знать индекс информации, которую я хочу, чтобы последовательно извлекать его, и это изменяется. Я также попытался кормить его через StreamReader и говорить

if (line.Contains("Case Number")) 
{ 
    tbReport.AppendText("Case Number: " + line.Remove(0, 13) + "\r\n"); 
} 

который получает мне информацию, которую я хочу, но делает это очень трудно сделать что-нибудь с.

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

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

Спасибо.

+1

Можете ли вы привести пример «других кусочков»? Не зная точно, как это выглядит, мы не можем написать вам хороший ответ. –

ответ

2

Это даст вам коллекцию со всеми парами ключ/значение.

List<KeyValuePair> items = new List<KeyValuePair>(); 

var line = reader.ReadLine(); 
while (line != null) 
{ 
    int pos = line.IndexOf(':'); 
    items.Add(new KeyValuePair(line.Substring(0, pos), line.Substring(pos+1)); 

    line = reader.ReadLine(); 
} 

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

class LogEntry 
{ 
    public string CaseNumber { get; set; } 
    public string User { get; set; } 
    public string Software{ get; set; } 
    public string DateStarted { get; set; } 
    public string DateEnded { get; set; } 
} 

List<LogEntry> items = new List<LogEntry>(); 

var line = reader.ReadLine(); 
var currentEntry = new LogEntry(); 
while (line != null) 
{ 
    if (line == "") //empty line = new log entry. Change to your delimiter. 
    { 
     items.Add(currentEntry); 
     currentEntry = new LogEntry(); 
    } 

    int pos = line.IndexOf(':'); 
    var name = line.Substring(0, pos).Replace(" ", string.Empty); 
    var value = line.Substring(pos+1); 

    var pi = entry.GetType().GetProperty(name); 
    pi.SetValue(entry, value, null); 


    line = reader.ReadLine(); 
} 

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

+0

Это дало мне именно то, что мне было нужно, и познакомило меня с KeyValuePairs. Большое спасибо. –

0

Звучит как хороший случай для кандидата RegExp:

http://www.regular-expressions.info/dotnet.html

Они не слишком легко узнать, но как только вы получите базовые знания, они не могут быть избитым для такого рода задач.

0

Это не простой ответ, но может быть, хотя вы можете использовать регулярное выражение для разбора информации?

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

Так что я могу видеть, то его как:

Если строка начинается с AZ, затем (AZ или AZ или 0-9 или пробел) от нуля до много раз, затем следуют : затем пробел, а затем значение.

Так что если вы делаете регулярное выражение для этого (если вы будете ждать некоторое время, я попытаюсь сделать это для вас), то вы можете проверить каждую строку с этим. Если он совпадает, то мы также можем использовать регулярные выражения, чтобы вывести последнюю часть и «ключ». Если он не совпадает, мы просто добавляем его к последнему ключу.

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

Как и было обещано здесь является отправной точкой для регулярного выражения:

^(?'key'[A-Z][a-z,A-Z,0-9,\s]+):\s(?'value'.+)

Так, чтобы попробовать и сказать, что он делает, мы должны идти, хотя каждая часть:

  • ^ гарантирует, что совпадение начинается с начала строки
  • (? 'Key' - это синтаксис для начала группы «захвата». Регулярное выражение затем даст нам доступ к легкому «ключевому» элементу регулярного выражения.
  • Мы, которые с [A-Z] - это группа, которая будет соответствовать любой большой букве. Но только один
  • [az, AZ, 0-9, \ s] + - как и предыдущая группа, но только для всех больших или маленьких букв, чисел и пробелов (\ s), плюс за пределами группа сообщает, что она может соответствовать нескольким.
  • Затем мы просто заканчиваем группу и выкладываем * :, а затем пробел.
  • Затем мы начинаем новую группу значение группы, так же как и ключевую группу.
  • Тогда мы просто напишем . (это означает, что все), а затем просто + после того, чтобы сделать его поймать больше, чем один

Я на самом деле думаю, что вы можете просто взять всю строку, а только соответствовать:

RegEx.Matches (или что-то в этом роде) и зацикливайтесь над ними.

Тогда просто возьмите match.Groups ["key"] и match.Groups ["value"] и поместите в свой массив. (Извините, у меня нет Visual Studio для тестирования)

+0

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

+0

Hi David, Я опубликовал регулярное выражение, которое швы для работы. –

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