2

鉴于此日志文件,我如何读取包含多个新行 ( \n) 的行和StreamReader? 该ReadLine方法从字面上返回每一行,但一条消息可能跨越多行。

否决票的大图

这是我到目前为止所拥有的

using (var sr = new StreamReader(filePath))
using (var store = new DocumentStore {ConnectionStringName = "RavenDB"}.Initialize())
{
    IndexCreation.CreateIndexes(typeof(Logs_Search).Assembly, store);

    using (var bulkInsert = store.BulkInsert())
    {
        const char columnDelimeter = '|';
        const string quote = @"~";
        string line;

        while ((line = sr.ReadLine()) != null)
        {
            batch++;
            List<string> columns = null;
            try
            {
                columns = line.Split(columnDelimeter)
                                .Select(item => item.Replace(quote, string.Empty))
                                .ToList();

                if (columns.Count != 5)
                {
                    batch--;
                    Log.Error(string.Join(",", columns.ToArray()));
                    continue;
                }

                bulkInsert.Store(LogParser.Log.FromStringList(columns));

                /* Give some feedback */
                if (batch % 100000 == 0)
                {
                    Log.Debug("batch: {0}", batch);
                }

                /* Use sparingly */
                if (ThrottleEnabled && batch % ThrottleBatchSize == 0)
                {
                    Thread.Sleep(ThrottleThreadWait);
                }
            }
            catch (FormatException)
            {
                if (columns != null) Log.Error(string.Join(",", columns.ToArray()));
            }
            catch (Exception exception)
            {
                Log.Error(exception);
            }
        }
    }                   
}

和模型

public class Log
{
    public string Component { get; set; }
    public string DateTime { get; set; }
    public string Logger { get; set; }
    public string Level { get; set; }
    public string ThreadId { get; set; }
    public string Message { get; set; }
    public string Terms { get; set; }

    public static Log FromStringList(List<string> row)
    {
        Log log = new Log();

        /*log.Component = row[0] == string.Empty ? null : row[0];*/
        log.DateTime = row[0] == string.Empty ? null : row[0].ToLower();
        log.Logger = row[1] == string.Empty ? null : row[1].ToLower();
        log.Level = row[2] == string.Empty ? null : row[2].ToLower();
        log.ThreadId = row[3] == string.Empty ? null : row[3].ToLower();
        log.Message = row[4] == string.Empty ? null : row[4].ToLower();

        return log;
    }
}
4

3 回答 3

3

我会使用Regex.Split2013-06-19并在每个错误开始时将文件分解为与日期模式(例如)匹配的任何内容。

于 2013-06-20T20:49:35.820 回答
2

如果您可以将整个文件读入内存(即File.ReadAllText),那么您可以将其视为单个字符串并使用正则表达式在日期上进行拆分,或诸如此类。

占用更少内存的更通用的解决方案是逐行读取文件。将行附加到缓冲区,直到您获得以所需值开头的下一行(在您的情况下为日期/时间戳)。然后处理该缓冲区。例如:

StringBuilder buffer = new StringBuilder();
foreach (var line in File.ReadLines(logfileName))
{
    if (line.StartsWith("2013-06-19"))
    {
        if (sb.Length > 0)
        {
            ProcessMessage(sb.ToString());
            sb.Clear();
        }
        sb.AppendLine(line);
    }
}
// be sure to process the last message
if (sb.Length > 0)
{
    ProcessMessage(sb.ToString());
}
于 2013-06-20T21:17:42.917 回答
0

很难看到你的文件。但我会说逐行阅读并附加到某个变量。检查消息的结尾。当你看到它时,对那个变量中的消息做任何你想做的事情(插入数据库等),然后继续阅读下一条消息。

Pseudo code

read the line
variable a = a +  new line
if end of message
    insert into DB
    reset the variable
continue reading the message.....
于 2013-06-20T21:04:52.937 回答