3

要阅读我尝试了这段代码:

在 Form1 的顶部,我做了:

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

在构造函数中我做了:

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

函数加载键:

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 单击事件中更改键或值时如何编写的问题。

4

6 回答 6

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;
于 2012-10-11T16:57:38.090 回答
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()));
于 2012-10-11T17:00:56.563 回答
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 指出的那样,您不需要过滤掉任何重复项,因为该文件应该从字典生成,并且不应包含重复项。 我强烈建议找出您的文件重复的原因,并解决该问题。 然后,您可以大大简化将文件加载到字典中的功能,删除分组和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;
于 2012-10-11T17:24:57.853 回答
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 中。

于 2012-10-11T16:59:02.673 回答
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}

于 2012-10-11T19:49:14.040 回答
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,添加了不带的替代解决方案。

于 2012-10-11T16:58:21.240 回答