2012-12-21 35 views
2

我有一個文本文件,它看起來像將字符串轉換爲一個多層次的解釋

tabs.main="******" 
tabs.settings="******" 

settings.setting1="******" 
settings.setting2="******" 
settings.setting3="******" 
settings.setting4="******" 

settings.setting5.title="******" 
settings.setting5.settingoption1="******" 
settings.setting5.settingoption2="******" 

我希望能夠做的是解析成一個多層次的解釋這一點。例如,我會有一個根字典,看起來像這個Dictionary<string, object>,並且我將擁有它們自己的標籤和設置,這兩個標籤和設置都是Dictionary<string, object>。在一個圖形化的形式,我想要的是:

Dictionary<string, object> 
    -> Dictionary<"tabs", object> 
     -> Dictionary<"main", "*******"> 
     -> Dictionary<"settings", "*******"> 
    -> Dictionary<"settings", object> 
     -> Dictionary<"setting1", "*******"> 

等等等等。這可能嗎?如果是這樣,有人能給我一個正確的方向指針。

回答

1

你要碰到的問題是,一些你的鑰匙都將需要被存儲在與值(字符串大概)的字典,其中一些將需要存儲的字典。

在你的榜樣,你所列:

settings.setting5="******" 
settings.setting5.settingoption1="******" 

這兩條線相互矛盾。 settings.settings5會讓密鑰settings5在字典中存儲一個值,但下一行需要將settings5設置爲其他值的字典。

你可以寫一段代碼是這樣的:

var settings = new Dictionary<string, object>(); 
var lines = File.ReadAllLines("..."); 
foreach (var line in lines) 
{ 
    var parts = line.Split(new char[] { '=' }, 2); 
    if (parts.Length != 2) continue; 

    var keys = parts[0].Split('.'); 
    var value = parts[1]; 

    var dict = settings; 
    for (int i = 0; i < keys.Length - 1; i++) 
    { 
     if (!dict.ContainsKey(keys[i])) 
      dict.Add(keys[i], new Dictionary<string, object>()); 
     dict = (Dictionary<string, object>)dict[keys[i]]; 
    } 

    dict.Add(keys[keys.Length - 1], value); 
} 
  1. 它沒有任何錯誤檢查。
  2. 你會發現雖然它填充你的對象。從中檢索值是一種痛苦。因爲你必須將每個結果轉換爲字符串或其他字典。

無論哪種方式,你會發現你最有可能想避免嘗試創建字典詞典爲此目的。

+0

我知道,在發佈我的問題後,我意識到了這一點。我相應地修改了它。這實際上是我最終做到的!實際上,我正在使用DynamicObject訪問字典來處理這些痛苦! – jduncanator

2

詞典並不是真的被設計成以這種方式保存你的數據。您可以創建類來表示您的文件並將數據加載到它們中。基於你展示的東西可能會奏效。

public class File 
{ 
    private List<Setting> settings = new List<Setting>(); 
    public Tab Tab { get; set; } 
    public List<Setting> Settings { get{ return settings; } } 
} 

public class Tab 
{ 
    public string Main{ get; set;} 
    public string Settings{ get; set;} 
} 

public class Setting 
{ 
    private List<string> options = new List<string>(); 
    public string Value{ get; set; } 
    public List<string> Options{ get{ return options;} } 
} 
+0

這將在DynamicObject Deserializer中使用,因此具有預定義的類佈局將不是最佳選擇。但是,如果內容是靜態的,這就是我的做法!謝謝! – jduncanator

0

請考慮使用字典以外的對象,但要回答你的問題。

請注意,此數據結構不允許具有相同鍵的字典和字符串值。

static Dictionary<string,object> Parse(string contents) 
{ 
    var root = new Dictionary<string,object>(); 

    using (var rdr = new StringReader(contents)) 
    { 
     string line; 
     var equals = new [] {'='}; 
     while(null != (line = rdr.ReadLine())) 
     { 
     if(!string.IsNullOrEmpty(line)) 
     { 
      var keyValue = line.Split(equals, 2); 
      AddValue(root, keyValue[0], keyValue[1]); 
     } 
     } 
    } 

    return root; 
} 

static void AddValue(Dictionary<string,object> dict, string dottedKeys, string value) 
{ 
    string [] keys = dottedKeys.Split('.'); 
    for(var i = 0; i < keys.Length - 1; i++) 
    { 
     var key = keys[i]; 
     dict = GetOrAdd(dict, key); 
    } 
    dict[keys[keys.Length - 1]] = value; 
} 

static Dictionary<string,object> GetOrAdd(Dictionary<string,object> parent, string key) 
{ 
    object o; 
    Dictionary<string,object> childDict; 
    if(parent.TryGetValue(key, out o)) 
     childDict = (Dictionary<string,object>) o; // This will throw when adding a dictionary to a value. 
    else 
     parent[key] = childDict = new Dictionary<string,object>(); 
    return childDict; 
} 

static string [email protected]" 
tabs.main=""******"" 
tabs.settings=""******"" 

settings.setting1=""******"" 
settings.setting2=""******"" 
settings.setting3=""******"" 
settings.setting4=""******"" 
settings.setting5=""******"" 

settings.setting6.settingoption1=""******"" 
settings.setting6.settingoption2=""******"" 
"; 
0

其實我最終設法糾正一些代碼,自己在會這樣,但是我很討厭浪費人民的時間來回答這個問題,我將標誌着賈森的問題的答案,因爲它是有點兒什麼我想出了,他幫我寫了我的代碼!

Dictionary<string, object> _dic = new Dictionary<string, object>(); 
using(StreamReader reader = new StreamReader(file)) 
{ 
    string text; 
    while ((text = reader.ReadLine()) != null) 
    { 
     if (text.Equals(String.Empty)) 
      continue; 
     string line = text.Trim(); 
     string[] keyval = line.Split('='); 
     string value = keyval[1].Trim('"'); 
     string[] keys = keyval[0].Split('.'); 
     Dictionary<string, object> prevDic = _dic; 
     for (int i = 0; i < keys.Length; i++) 
     { 
      if (i + 1 != keys.Length) 
      { 
       Dictionary<string, object> temp = new Dictionary<string, object>(); 
       if (prevDic.ContainsKey(keys[i])) 
       { 
        prevDic = prevDic[keys[i]] as Dictionary<string, object>; // Avoids exceptions when trying to cast the string value to a dictionary 
        continue; 
       } 
       else 
       { 
        prevDic.Add(keys[i], temp); 
        prevDic = temp; 
       } 
      } 
      else 
      { 
       prevDic.Add(keys[i], value); 
      } 
     } 
    } 
} 

感謝大家的幫助!