2013-06-20 62 views
2

鑑於此日誌文件,如何使用StreamReader讀取多行(\n)的行? ReadLine方法逐字地返回每一行,但消息可能會跨越一行。如何使用跨越多行的c#解析文本文件中的消息?

Larger Image for the down votes

這裏是我迄今爲止

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; 
    } 
} 
+0

我忘了發佈我的代碼..對不起。 –

+1

我的眼睛!在dowvotes進來之前修復圖像 –

+0

這些消息是如何分開的?有一段時間?只需要模式來區分消息,然後決定一個正則表達式是否更合適。 – Kash

回答

3

我會用Regex.Split,並打破該文件多達上任何日期模式匹配(例如,在每個錯誤的開始處,例如2013-06-19)。

+0

我自己也在想這些。 –

+0

看起來像最好的選擇 –

+0

按日期時間拆分。 –

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..... 
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()); 
} 
+0

吉姆,其中之一我的擔憂是記憶,謝謝你的注意。 –