2012-03-27 56 views
0

我試圖解析一個相當長的日誌文件,並創建的問題更好更易於管理的列表。使用C#字典來分析日誌文件

我能夠讀取並解析出由行個人日誌行,但我需要做的是隻顯示獨特的條目,出現頻率高於其他一些錯誤,總是用相同的文字記錄。

我要去嘗試做的是創建一個Dictionary對象來保存每個唯一的入口,當我通過日誌文件時,搜索Dictionary對象,看是否相同的值已經在那裏。

這裏是我的代碼有粗樣品(進展中的工作,我希望我所有的語法右)不起作用。出於某種原因,這個腳本不會看到任何明顯的條目(如果語句根本不會通過):

string[] rowdta = new string[4]; 
    Dictionary<string[], int> dict = new Dictionary<string[], int>(); 
    int ctr = -1; 
    if (linectr == 1) 
     { 
      ctr++; 
      dict.Add(rowdta, ctr); 
     } 
     else 
     { 
      foreach (KeyValuePair<string[], int> pair in dict) 
      { 
       if ((pair.Key[1] != rowdta[1]) || (pair.Key[2] != rowdta[2])| (pair.Key[3] != rowdta[3])) 
       { 
        ctr++; 
        dict.Add(rowdta, ctr); 
       } 
      } 
     } 

一些樣本數據: 第一行

rowdta[0]="ErrorType"; 
    rowdta[1]="Undefined offset: 0"; 
    rowdta[2]="/url/routesDisplay2.svc.php"; 
    rowdta[3]="Line Number 5"; 

二號線

rowdta[0]="ErrorType"; 
    rowdta[1]="Undefined offset: 0"; 
    rowdta[2]="/url/routesDisplay2.svc.php"; 
    rowdta[3]="Line Number 5"; 

3號線

rowdta[0]="ErrorType"; 
    rowdta[1]="Undefined variable: fvmsg"; 
    rowdta[2]="/url/processes.svc.php"; 
    rowdta[3]="Line Number 787"; 

因此,在這個詞典中,第一行和第三行將包含2個條目。

我也與n還沒有找到在日誌文件文本的任何變化如下嘗試這樣做。

if (!dict.ContainsKey(rowdta)) {} 

有人可以幫助我得到這個語法正確嗎?我只是C#的新手,但這應該是相對直接的。與往常一樣,我認爲這應該是足夠的信息來開始對話。如果你想要/需要更多的細節,請讓我知道。

+0

你能後的代碼,你正在填充rowdta? – dcp 2012-03-27 17:04:55

+1

嘗試使用hashset而不是字典(因爲它似乎不再需要這些值)。另外,嘗試使用.Equals()而不是==來比較字符串。 – 2012-03-27 17:08:30

+0

謝謝大家對此的幫助。我會嘗試各種迭代,然後更新什麼可行。 – radi8 2012-03-27 18:22:52

回答

1

爲您的字符串創建一個包裝,它實現了IEquatable

public class LogFileEntry :IEquatable<LogFileEntry> 
{ 
    private readonly string[] _rows; 

    public LogFileEntry(string[] rows) 
    { 
     _rows = rows; 
    } 

    public override int GetHashCode() 
    { 
     return 
      _rows[0].GetHashCode() << 3 | 
      _rows[2].GetHashCode() << 2 | 
      _rows[1].GetHashCode() << 1 | 
      _rows[0].GetHashCode(); 
    } 

    #region Implementation of IEquatable<LogFileEntry> 

    public override bool Equals(Object obj) 
    { 
     if (obj == null) 
      return base.Equals(obj); 

     return Equals(obj as LogFileEntry); 
    } 

    public bool Equals(LogFileEntry other) 
    { 
     if(other == null) 
      return false; 

     return _rows.SequenceEqual(other._rows); 
    } 

    #endregion 
} 

然後用在你的字典:

var d = new Dictionary<LogFileEntry, int>(); 

var entry = new LogFileEntry(rows); 
if(d.ContainsKey(entry)) 
{ 
    d[entry] ++; 
} 
else 
{ 
    d[entry] = 1; 
} 

或者創建由@dasblinkenlight提出類似的自定義比較,並使用如下

public class LogFileEntry 
{ 
} 

public class LogFileEntryComparer : IEqualityComparer<LogFileEntry>{ ... } 

var d = new Dictionary<LogFileEntry, int>(new LogFileEntryComparer()); 

var entry = new LogFileEntry(rows); 
if(d.ContainsKey(entry)) 
{ 
    d[entry] ++; 
} 
else 
{ 
    d[entry] = 1; 
} 
+0

我的Equals和GetHashCode的實現有點粗糙和準備就緒。你顯然需要做一些錯誤檢查,並可能提供更好的哈希碼。 – Phil 2012-03-27 17:21:31

+0

+1。也使對象具有有意義的屬性而不是僅僅數組的行將有助於可讀性(並且可能保存一些內存 - 即行[3]看起來像整數行號)。 – 2012-03-27 17:22:54

+0

這似乎工作,但我仍然遇到兩個問題:1 - 由於logFileEntry是一個數組,Sum(o => o.GetHashCode());是無效的。此外,它似乎並沒有像我期望的那樣找到唯一的值。我不確定什麼是錯誤的調試器不會在Equals(..)函數中斷開。我試圖闖入d.ContainsKey(入口),但它不會。有任何想法嗎? – radi8 2012-03-27 19:43:19

1

您看到問題的原因是,如果不提供自定義IEqualityComparer<string[]>或在其中編寫包裝器,則不能將字符串數組用作字典中的鍵。

編輯這裏是一個快速和骯髒的執行自定義比較的:

private class ArrayEq<T> : IEqualityComparer<T[]> { 
    public bool Equals(T[] x, T[] y) { 
     return x.SequenceEqual(y); 
    } 
    public int GetHashCode(T[] obj) { 
     return obj.Sum(o => o.GetHashCode()); 
    } 
} 

這裏是你如何使用它:

var dd = new Dictionary<string[], int>(new ArrayEq<string>()); 
dd[new[] { "a", "b" }] = 0; 
dd[new[] { "a", "b" }]++; 
dd[new[] { "a", "b" }]++; 
Console.WriteLine(dd[new[] { "a", "b" }]); 
+0

你打算鏈接到http://msdn.microsoft.com/en-us/library/ms132151.aspx – phoog 2012-03-27 17:09:23

+0

@phoog絕對!感謝您的支持。 – dasblinkenlight 2012-03-27 17:12:33

0

的問題是,數組平等是引用相等。換句話說,它不依賴於存儲在數組中的值,它僅取決於數組的標識。

一些解決方案

  • 使用Tuple持有該行數據
  • 使用匿名類型來保存行數據
  • 創建一個自定義類型來保存行數據,並且,如果它是一個類,覆蓋Equals和GetHashCode。
  • 創建IEqualityComparer的自定義實現,以根據它們的值比較數組,並在創建時將其傳遞到字典。