如何将C#字符串字典读写到文件中?

8
我有一个字典对象,想要将其写入磁盘并能够从磁盘中读取。最好不要使用第三方库。是否有一种简单的方法可以在常规C# 4中实现? 答案已接受。 总结:
选项1 - 使用JavaScriptSerializer 优点:不需要第三方库。此外,使用更现代的格式,即JSON。
缺点:难以阅读 - 没有格式。此外,即使应用程序与Web无关,也需要引用不常用的System.Web.Extension程序集。
解决方案:
写入:
File.WriteAllText("SomeFile.Txt", new JavaScriptSerializer().Serialize(dictionary));

阅读:

var dictionary = new JavaScriptSerializer()
    .Deserialize<Dictionary<string, string>>(File.ReadAllText("SomeFile.txt"));

选项2 - 使用Linq to Xml

优点:无需第三方库。通常不需要添加其他引用。易于阅读。

缺点:XML不如JSON等更现代的格式受欢迎。

编写:

new XElement("root", d.Select(kv => new XElement(kv.Key, kv.Value)))
            .Save(filename, SaveOptions.OmitDuplicateNamespaces);

阅读:

var dictionary = XElement.Parse(File.ReadAllText(filename))
                .Elements()
                .ToDictionary(k => k.Name.ToString(), v => v.Value.ToString());

选项3 - 使用JSON.NET

优点:易于阅读。现代格式。

缺点:需要第三方库。

解决方案:

编写:

File.WriteAllText("SomeFile.Txt", JsonConvert.SerializeObject(dictionary));

阅读:

var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>
    (File.ReadAllText("SomeFile.txt"));

2
一个简单的序列化/反序列化就可以解决问题。例如,使用 JavaScriptSerializer 只需要一行代码。 - L.B
1
你也可以使用 XML 序列化:http://web.archive.org/web/20100703052446/http://blogs.msdn.com/b/psheill/archive/2005/04/09/406823.aspx - gcarvelli
@killermonkey50 IDictionary 不被 XmlSerializer 支持。 - L.B
Jonesy,这是一种积极鼓励的存储个人信息并与他人分享的方式。请参见:http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/。 - zumalifeguard
1
@L.B. 我知道,该解决方案创建了一个Entry类并使用列表来存储它。这不是最优雅的方法,但它可以工作。 - gcarvelli
显示剩余6条评论
3个回答

11

如果没有像JSON.Net这样的第三方库,可以使用JavaScriptSerializer

File.WriteAllText("SomeFile.Txt", new JavaScriptSerializer().Serialize(dictionary));

从文件中获取字典:

var dictionary = new JavaScriptSerializer()
    .Deserialize<Dictionary<string, string>>(File.ReadAllText("SomeFile.txt"));

唯一需要记住的是在项目引用中添加对System.Web.Extensions的引用,然后您就可以在using System.Web.Script.Serialization;后使用JavaScriptSerializer了。


或者使用JSON.Net将字典序列化为JSON,然后将其写入文件,最后进行反序列化:

Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("1", "Some value 1");
dictionary.Add("2", "Something");

将字典存储在文件中:

string json = JsonConvert.SerializeObject(dictionary);
File.WriteAllText("SomeFile.Txt", json);

从文件中获取字典:

Dictionary<string, string> previousDictionary =
 JsonConvert.DeserializeObject<Dictionary<string, string>>
                                 (File.ReadAllText("SomeFile.txt"));

对于这两种选项的比较,请参见:JSON.NET JsonConvert vs .NET JavaScriptSerializer


1
我会避免使用任何第三方库。 - L.B
1
@zumalifeguard 修改了答案以包含仅 .Net 选项。 - Habib
Habib,谢谢你的回答。请问你能否删除答案中关于JSON.NET的参考?不清楚为什么要提到它。读起来像是在指出两种不同的解决方案,但如果是这样的话,应该更明确地说明“我推荐两种解决方案”,并指出哪个是哪个。这样对读者来说会更容易。我的偏好是只使用JavaScriptSerializer版本。 - zumalifeguard
我正在尝试各种解决方案。到目前为止,我喜欢JavaScriptSerializer,这是我的首选。 - zumalifeguard
JavaScriptSerializer需要在您的项目中包含System.Web.Extension。我不确定这是否很重要,但我认为它并不是什么大问题。与XML版本易于阅读的格式相比,JavaScriptSerializer使使用记事本查看文本变得困难。我将在原始问题中更新选项、给定解决方案以及优缺点。 - zumalifeguard
显示剩余4条评论

3

编写字典的最简单方式是创建一个列表,其中每个字典条目都转换为XElement。然后,创建一个根XElement,其中列表是根的值。使用XElement的原因是您可以使用它的Save方法将其存储为XML文件。以下是在一行中执行此操作的示例(其中d是字典):

new XElement("root", d.Select(kv => new XElement(kv.Key, kv.Value)))
            .Save(filename, SaveOptions.OmitDuplicateNamespaces);

要将文件读入字典中,请使用XElement的Parse静态方法,并将文件的整个内容传递给它,可以使用File.ReadAllText进行读取。Parse返回一个XElement对象,即根元素。然后,您可以遍历根元素的Elements()并将其转换为字典。您可以在一行中完成此操作:

var d = XElement.Parse(File.ReadAllText(filename))
                .Elements()
                .ToDictionary(k => k.Name.ToString(), v => v.Value.ToString());

以下是一种使用方法组织的代码版本:
public static void Store(IDictionary<string, string> d, string filename)
{
    new XElement("root", d.Select(kv => new XElement(kv.Key, kv.Value)))
                .Save(filename, SaveOptions.OmitDuplicateNamespaces);
}
 public static IDictionary<string, string> Retrieve(string filename)
{
    return XElement.Parse(File.ReadAllText(filename))
                   .Elements()
                   .ToDictionary(k => k.Name.ToString(), v => v.Value.ToString());
}

2
如果字典的是像用户员工等复杂对象怎么办? - L.B
1
你的解决方案只适用于基本类型,如果我写一个解决方案,我更喜欢它能够与Dictionary<T1,T2>一起使用。 - L.B
但是你知道,现在它变得有点复杂了。因此,不要重复造轮子,使用适合你的序列化器。 - L.B
L.B,不要重复造轮子。你所说的关于通用性更好的观点是正确的,如果需要这样的话,就不会使用这种技术。我想提醒你一下原始问题是什么。那个人想要将“字符串”字典写入磁盘。假设他已经有了这样的字典,并想知道最简单和最好的方法来保存它。工欲善其事必先利其器。如果你只有字符串(这很常见),你可以使用这种技术。 - zumalifeguard
当您使用new XElement(kv.Key, kv.Value)时,必须遵守XML标记的命名规则。例如,您不能使用以数字开头的kv.Key。因此,您不能保存具有任意键的字典,它们都必须符合XML标记的命名规则。 - Max Jacobi
显示剩余4条评论

2
一个老的线程,但我想添加一个简单的答案。 对于.NET 5和.NET Core 3.0及以上版本,您只需使用JsonSerializer即可。 您只需要将键和值序列化即可。
写入:
using System.Text.Json;
File.WriteAllText(fileName, JsonSerializer.Serialize(dictionary));

并且阅读:

JsonSerializer.Deserialize<Dictionary<string, string>>(fileName);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接