解析不一致的日志文件

时间:2011-01-21 11:50:36

标签: c# parsing text

我有一个我要解析并加载到数据库中的日志文件。我正在努力解决它的最佳方法。

日志文件的格式为类别:信息

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");
}

它为我提供了我想要的信息,但却很难做到。

我觉得我最好离开数组路径,但我可以做一些关于如何在数组中搜索该类别的指导,然后解析信息。

一旦我能准确地解析它,将它添加到数据库中应该是相当直接的。因为这是我第一次尝试这个,所以我会对任何有关此问题的最佳方法的提示或指导感兴趣。

感谢。

3 个答案:

答案 0 :(得分: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();
}

请注意,我没有测试过代码(只是在这里直接编写)。您必须添加错误检查等。最后一种选择并不是很有效,但应该做得好。

答案 1 :(得分:0)

听起来像是RegExp的好候选案例:

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

它们不是太容易学习,但是一旦你掌握了基本的理解,它们就不会被这些任务所打败。

答案 2 :(得分:0)

这不是一个简单的答案,但您是否可以使用正则表达式来解析信息?

正则表达式有点像硬核,但是它们可以很容易地解析高级文件。

所以在我能看到的内容中,它就像:

  

如果一条线以A-Z开头,那么(a-z或A-Z或0-9或空格)从零到多次,然后是a:然后是空格,然后是值。

所以如果你为它做一个正则表达式(如果你等了一会儿,我会尝试为你制作一个),那么你可以测试每一行。如果它匹配,那么我们也可以使用正则表达式来取出最后一部分和“密钥”。如果它不匹配,那么我们只需将它附加到最后一个键。

要注意它并非完全万无一失,因为新系列可以这样开始,但我认为它是我们能做的最好的事情。

这里承诺的是正则表达式的起点:

^(?'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方便测试它)