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", "*******">

などなど。これは可能ですか?もしそうなら、誰かが私に正しい方向への指針を与えることができますか.

4

4 に答える 4

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;} }
}
于 2012-12-21T04:21:10.647 に答える
1

あなたが遭遇しようとしている問題は、あなたのキーのいくつかが値 (おそらく文字列) とともにディクショナリに保存される必要があり、それらのいくつかがディクショナリとともに保存される必要があるということです。

あなたがリストしたあなたの例では:

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

この 2 つの行は互いに矛盾しています。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. それがあなたのオブジェクトに移入している間、あなたはそれを見つけるでしょう. そこから値を取得するのは面倒です。各結果を文字列または別の Dictionary にキャストする必要があるためです。

いずれにせよ、この目的のために辞書の辞書を作成しようとするのは避けたいと思うでしょう。

于 2012-12-21T04:24:49.667 に答える
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);
            }
        }
    }
}

みんな助けてくれてありがとう!

于 2012-12-21T04:39:13.483 に答える
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 fileContents=@"
tabs.main=""******""
tabs.settings=""******""

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

settings.setting6.settingoption1=""******""
settings.setting6.settingoption2=""******""
";
于 2012-12-21T04:29:11.980 に答える