2012-12-21 34 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); 
      } 
     } 
    } 
} 

感谢大家的帮助!