如何写入文本文件并从文本文件读回/到词典<string,list <string>&gt;?</string,list <string>

时间:2012-10-11 16:53:29

标签: c#

要阅读我试过这段代码:

在Form1的顶部,我做了:

Dictionary<string, List<string>> LocalyKeyWords = new Dictionary<string, List<string>>();

在构造函数中我做了:

keywords = @"d:\Keywords.txt";
            if (File.Exists(keywords))
            {
                LoadKeys(LocalyKeyWords, keywords);
            }

功能LoadKeys:

private void LoadKeys(Dictionary<string,List<string>> disctionary, string FileName)
        {
            var lines = File.ReadAllLines(keywords).Select(l => l.Split(','));
            var dict = new Dictionary<string, List<string>>();
            foreach(var splits in lines)
            {
                var key = splits.First();
                var value = splits.Skip(1).ToList();
                try {dict.Add(key, value);
                }
                catch(Exception ex)
                {  } } 
        }

没有例外,但在调用函数后的构造函数中完成所有操作后,LocalyKeyWords为空。


这就是我今天写文件的关键和值:

private void button6_Click(object sender, EventArgs e)
        {

            using (var w = new StreamWriter(keywords))
            {
                crawlLocaly1 = new CrawlLocaly();
                crawlLocaly1.StartPosition = FormStartPosition.CenterParent;
                DialogResult dr = crawlLocaly1.ShowDialog(this);
                if (dr == DialogResult.OK)
                {
                    if (LocalyKeyWords.ContainsKey(mainUrl))
                    {
                        LocalyKeyWords[mainUrl].Clear();
                        LocalyKeyWords[mainUrl].Add(crawlLocaly1.getText());
                    }
                    else
                    {
                        LocalyKeyWords[mainUrl] = new List<string>();
                        LocalyKeyWords[mainUrl].Add(crawlLocaly1.getText());
                    }
                    foreach (KeyValuePair<string, List<string>> kvp in LocalyKeyWords)
                    {
                        w.WriteLine(kvp.Key + "," + string.Join(",", kvp.Value));
                    }
                }
            } 
        }

也许现在你将能够解决在构造函数中加载键和值的问题,并解决每次在button6点击事件中更改键或值时如何编写的问题。

6 个答案:

答案 0 :(得分:3)

var lines = File.ReadAllLines("path/to/file").Select(l => l.Split(','));
var dict = new Dictionary<string, List<string>();
foreach(var splits in lines) 
{
    var key = splits.First();
    var value = splits.Skip(1).ToList();
    try {dict.Add(key, value);}
    catch(Exception ex) { //TODO: handle }
}
return dict;

答案 1 :(得分:2)

如果你有一个非常大的文件,强烈建议使用ReadLines而不是ReadAllLinesReadLines是延迟执行,并且不会将所有行加载到内存中,ReadAllLines是将所有行加载到内存时没有太多优化:

var result = File.ReadLines("text.txt")
                 .Select(line => line.Split(','))
                 .ToDictionary(x => x.First(),
                               x => x.Skip(1).ToList());

如果你有相同的密钥,Dictionary不是一个好选择,你可以使用:

var result = File.ReadLines("text.txt")
            .Select(line => line.Split(','))
            .Select(x => new KeyValuePair<string, List<string>>(x.First(), x.Skip(1).ToList()));

答案 2 :(得分:2)

基于上述建议,这会将任何重复的键组合在一起,并为每个键提供唯一的值。

           // Turn the file into an Enumerable of lines
var dict = File.ReadLines("path/to/file")
           // For each line, turn it into an array of comma-separated values
           .Select(line => line.Split(','))
           // Group the lines together by their first token (the key)
           // The values of the groupings will be the "tokenized" lines
           .GroupBy(line => line[0])
           // Create a dictionary from the collection of lines, 
           // using the Key from the grouping (the first token)
           .ToDictionary(group => group.Key,
                         // Set the values of each entry to the arrays
                         // of tokens found for each key (merging 
                         // them together if a key was found multiple times)
                         group => group.SelectMany(values => 
                                  // ...ignoring the first token and filtering
                                  // out duplicate values
                                  values.Skip(1).Distinct().ToList()));
return dict;

例如,包含以下文本的文件:

1,a,b,c
1,c,d,e
2,e,f,g

将转换为以下字典:

1 : {a,b,c,d,e}
2 : {e,f,g}

正如@Vlad所指出的,您不需要过滤掉任何重复项,因为该文件应该从Dictionary生成,并且不应包含重复项。 我强烈建议找出文件重复的原因,然后解决问题。然后,您可以大大简化将文件加载到字典中的功能,删除分组和Distinct调用留下以下内容:

var dict = File.ReadLines("path/to/file")
           // For each line, turn it into an array of comma-separated values
           .Select(line => line.Split(','))
           // Create a dictionary from the collection of lines, 
           // using the the first token as the key
           .ToDictionary(tokens => tokens[0],
                         // Set the value of each entry to the a
                         // list containing each token on that line
                         // (after the first, which is the key)
                         tokens => tokens.Skip(1).ToList());
return dict;

答案 3 :(得分:1)

嗯,基本上你的阅读与写作相反。

您打开文件(var w = new StreamReader(keywords)),逐行阅读(while (w.Peek() >= 0) { var l = sr.ReadLine()); ...(甚至更好string l; while ((l = sr.ReadLine()) != null) { ...),并解析每一行。

对于解析一行,您可以使用string.Split将其拆分为逗号,因此您的键是部件列表中的第0个条目,其余部分是值。

编辑:在没有Peek的情况下添加了替代解决方案,感谢@Jon。

答案 4 :(得分:1)

string line = System.String.Empty;
using (StreamReader sr = new StreamReader("MyFile.txt")
{
    while ((line = sr.ReadLine()) != null)
    {
         string[] tokens = line.Split(',');    
         LocalKeyWords.Add(tokesn[0], tokens[1]);
    }
}

你也应该将它包装在try catch中。

答案 5 :(得分:1)

<强>代码:

var delimiter = new[] {','};

var splits = File.ReadLines("text.txt")
                 .Where(line => !string.IsNullOrWhiteSpace(line))
                 .Select(line => line.Split(delimiter));
                 // Add "StringSplitOptions.RemoveEmptyEntries" if you want
                 // Add ".Where(split => split.Length > 1)" to exclude empty keys

var lookup = splits.ToLookup(split => split[0], split => split.Skip(1));
var dict = lookup.ToDictionary(x => x.Key, x => x.SelectMany(s => s).ToList());

调试更少,但线路更少:

var dict = File.ReadLines("text.txt")
               .Where(line => !string.IsNullOrWhiteSpace(line))
               .Select(line => line.Split(delimiter))
               .ToLookup(split => split[0], split => split.Skip(1))
               .ToDictionary(x => x.Key, x => x.SelectMany(s => s).ToList());

示例输入:

  

1,a,b,c

     

2,a,b,c

     

1,a,e,d

     

3

     

2,一个

     

4,a,b

<强>输出:

  

1:{a,b,c,a,e,d}

     

2:{a,b,c,a}

     

3:{}

     

4:{a,b}