0

所以我正在尝试上传然后解析具有以下格式的文本文件:

3 月 29 日 19:23:51,667|DEBUG|1 |1:正在初始化 lorem ipsum...
3 月 29 日 19:23:31,682|ERROR|1 |1:启动 Foo.Bar.Launcher
System.Blah 时出现 Lorem.Ipsum.Exception。 LoremException: Lorem ipsum dolor sit amet, consectetur adipisicing elit...
    at System.Lorem.Ipsum.Dolor.foo()
    at System.Lorem.Ipsum.Dolor.foo()
...
Mar 30 22:23:23,667|DEBUG |1 |1: 正在初始化 lorem ipsum...
Apr 02 17:24:17,413|ERROR|4 |4: Lorem 无法 ipsum... System.DolorException: 对象引用未设置为对象的实例。
    在 Lorem.Ipsum.Dolor.IpsumDbController..ctor()

和错误类:

public class Error
{
    public int ID { get; set; }
    public string Date { get; set; }
    public string Description { get; set; }
    public string ErrorType { get; set; }
}

哪里有两个错误:

错误 1

Mar 29 19:23:33 - 是日期
System.Blah.LoremException - 是 ErrorType。
Lorem ipsum dolor sit amet, consectetur adipisicing elit - 是描述

错误 2

Apr 02 17:24:17 - 是日期
System.DolorException - 是 ErrorType。
你调用的对象是空的。- 是描述

有没有一种简单的方法可以解析字符串(通过正则表达式?或不?)?如果字符串包含 ERROR,我正在考虑拆分字符串,然后将下一行分配给 ErrorType。

我不太确定我会怎么做,所以任何帮助将不胜感激!

更新:模式确实不一致,所以我对 String.Split 解决方案不是很自信。

一般规则是:

全部 |错误| 将有一个 Date (我们的字符串 Date)、 System.blah.LoremException (我们的 ErrorType) ,然后是一个异常消息(我们的描述)

ErrorType & Description 可能与 ERROR 字符串内联或在下一行。

4

4 回答 4

1

我会结合使用 StreamReader 和正则表达式来处理解析。

    private static List<Error> ParseErrors(string filepath)
    {
        Regex parser = new Regex(@"^(?<date>\w{3}\s\d{1,2}\s\d{1,2}(?::\d{1,2}){2}),[^\|]+\|ERROR\|[^:]+\s*(?<description>.+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        string line = string.Empty;
        Match curMatch = null;
        var errorLog = new List<Error>();

        using (StreamReader sReader = new StreamReader(filepath))
        {
            while (!sReader.EndOfStream && (line = sReader.ReadLine()) != null)
            {
                curMatch = parser.Match(line);
                if (curMatch.Success)
                {
                    errorLog.Add(new Error()
                    {
                        ID = errorLog.Count, /* not sure how you assign ids? */
                        Date = curMatch.Groups["date"].Value.Trim(),
                        Description = curMatch.Groups["description"].Value.Trim(),
                        ErrorType = sReader.ReadLine().Trim()
                    });
                }
            }
        }
        return errorLog;
    }

这背后的逻辑基本上是遍历流逐行搜索与正则表达式的匹配。正则表达式本身被定制为仅适合“错误”行,因此它不会匹配“调试”等。

如果该行与表达式匹配,则将新的“错误”类实例放入列表中,并使用正则表达式中的解析值填充字段。要填写“ErrorType”字段,我只需阅读匹配后的下一行。

编辑

好的,我能看到的最好方法是在异常位于同一行时匹配错误消息末尾的尾随“...”,然后尝试进一步匹配。

修改后的代码:

    private static List<Error> ParseErrors(string filepath)
    {
        Regex parser = new Regex(@"^(?<date>\w{3}\s\d{2}\s\d{1,2}(?::\d{1,2}){2}),[^\|]+\|ERROR\|[^:]+:\s*(?<description>.+?)(?:\.\.\.\s*(?<type>.+))?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        string line = string.Empty;
        Match curMatch = null;
        var errorLog = new List<Error>();

        using (StreamReader sReader = new StreamReader(filepath))
        {
            while (!sReader.EndOfStream && (line = sReader.ReadLine()) != null)
            {
                curMatch = parser.Match(line);
                if (curMatch.Success)
                {
                    errorLog.Add(new Error()
                    {
                        ID = errorLog.Count, /* not sure how you assign ids? */
                        Date = curMatch.Groups["date"].Value.Trim(),
                        Description = curMatch.Groups["description"].Value.Trim(),
                        ErrorType = (curMatch.Groups["type"].Success ? curMatch.Groups["type"].Value : sReader.ReadLine().Trim())
                    });
                }
            }
        }
        return errorLog;
    }
于 2012-05-10T16:07:51.467 回答
1

如果你在循环中使用类似的东西......你也可以像我之前提到的那样使用 split ,这样可能会更有效一些

if (line.Contains("ERROR"))
                {
                    data = true;
                    continue;
                }


                if (data)
                    //here you deal with the following line
于 2012-05-10T15:55:38.040 回答
1

我会按照你的想法去做。拆分 上的每一行|,检查第二个元素是否相等ERROR,如果是,假设我需要处理该行和下一行。

于 2012-05-10T15:49:05.720 回答
0

我解决了它,虽然它不是最优雅的解决方案,所以如果您有其他答案,请随时在此处发布。

    public static List<Error> ParseErrors(string filepath)
    {
        //separated the two regex
        Regex dateRegex = new Regex(@"^\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex errorRegex = new Regex(@"((?<type>System.*?Exception):\s(?<description>.*\.))", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        string CurrentLine = string.Empty;
        string NextLine = string.Empty;

        List<Error> errorLog = new List<Error>();

        using (StreamReader sReader = new StreamReader(filepath))
        {
            while (!sReader.EndOfStream && (CurrentLine = sReader.ReadLine()) != null)
            {

                if (CurrentLine.Contains("|ERROR|"))
                {

                    Match DateMatch = dateRegex.Match(CurrentLine);
                    Match ErrorMatch = errorRegex.Match(CurrentLine);

                    string date = DateMatch.Groups[0].Value.Trim();
                    string errorType = string.Empty;
                    string description = string.Empty;

                    //Check if error type and description is residing in the current line, otherwise, check at the next line
                    if (!ErrorMatch.Groups["type"].Value.Equals("") && !ErrorMatch.Groups["description"].Value.Equals(""))
                    {
                        errorType = ErrorMatch.Groups["type"].Value.Trim();
                        description = ErrorMatch.Groups["description"].Value.Trim();
                    }
                    else
                    {
                        NextLine = sReader.ReadLine();
                        ErrorMatch = errorRegex.Match(NextLine);
                        errorType = ErrorMatch.Groups["type"].Value.Trim();
                        description = ErrorMatch.Groups["description"].Value.Trim();
                    }

                    Error NewError = new Error();
                    NewError.Date = date;
                    NewError.ErrorType = errorType;
                    NewError.Description = description;

                    //a bit lazy with the regex, just take the first sentence of the description if it has multiple sentences.
                    if (NewError.Description.Contains(". "))
                        NewError.Description = NewError.Description.Substring(0, NewError.Description.IndexOf(". "));

                    // Do not add if it's a custom exception.
                    if(!NewError.Description.Equals("") && !NewError.Description.Equals(""))
                        errorLog.Add(NewError);
                }
            }
        }

        return errorLog;

    }
于 2012-05-14T10:07:45.080 回答