Contents

我们经常需要读取一些如下的属性文件,然后把他们放到一个Dictionary里面。

1
2
Name = Dawei XU
Email = dawei.xu@gmail.com

在C#中可以用Linq很方便的实现这个功能。先看代码:

1
2
3
4
File.ReadAllLines(fileName)
.Select(line => line.Split(new[] {'='}, 2, StringSplitOptions.RemoveEmptyEntries))
.Where(split => split.Length == 2)
.ToDictionary(split => split[0].Trim(), split => split[1].Trim());

用到了如下Linq扩展方法:

  • Enumerable.Select,用来对每一行做split操作,分隔出Key和Value。注意这里要写上分隔成两段。另外要StringSplitOptions.RemoveEmptyEntries
  • Enumerable.Where,用来过滤到不符合Key-Value的行。
  • Enumerable.ToDictionary,把分隔成两段的第一段作为Key,第二个作为Value存在Dictionary里面。

但是这个做法有一个潜在的问题,就是如果属性文件中有重复的Key出现,比如:

1
2
3
Email = dawei.xu@hotmail.com
Name = Dawei XU
Email = dawei.xu@gmail.com

就会抛出ArgumentException

An element with the same key already exists in the Dictionary<TKey, TValue>.

解决办法就是用Enumerable.GroupBy把重复的Key合并在一起,然后可以根据需要使用第一次出现的或者最后一次出现的,下面的例子是采用最后一次出现的。同时因为用了GroupBy,最后的ToDictionary需要做一些相应的修改。

1
2
3
4
5
File.ReadAllLines(fileName)
.Select(line => line.Split(new[] {'='}, 2, StringSplitOptions.RemoveEmptyEntries))
.Where(split => split.Length == 2)
.GroupBy(split=>split[0].Trim())
.ToDictionary(group => group.Key.Trim(), group => group.Last().Last().Trim());
Contents