一、对象本地保存的基本问题
对象在程序运行时存储在内存中,程序关闭后会被垃圾回收机制销毁,无法保留状态。若需在程序再次运行时恢复对象状态,需将对象信息持久化到磁盘(如文件)中。
原始保存方式的局限
直接将对象属性按顺序写入文本文件(如People.obj),通过顺序读取还原对象,存在明显缺点:
强依赖顺序:存储与读取顺序必须完全一致,否则数据错乱;
可读性差:无法直观区分文件中各字段对应对象的哪个属性;
扩展性差:对象新增属性时,需修改存储和读取的全部逻辑。
二、序列化与反序列化
为解决原始保存方式的问题,引入 “序列化” 和 “反序列化” 机制:
序列化:将对象状态转换为可存储(如文件)或可传输(如网络)的格式(二进制、XML、JSON 等)的过程。
反序列化:将序列化后的格式(如二进制流、JSON 文本)还原为对象的过程。
三、三种常用序列化方式
1. 二进制序列化
将对象转换为二进制流,效率高、体积小,但可读性差(二进制无法直接看懂)。
核心组件
BinaryFormatter:位于System.Runtime.Serialization.Formatters.Binary命名空间,负责二进制序列化与反序列化。
使用步骤
标记类为可序列化:在类定义前添加
[Serializable]特性(否则序列化失败);创建文件流:通过
FileStream指定存储路径和模式(如FileMode.Create创建文件);实例化序列化器:创建
BinaryFormatter对象;执行序列化 / 反序列化:调用
Serialize()(写入对象)或Deserialize()(读取对象);释放资源:关闭文件流。
示例代码
// 1. 定义可序列化的类
[Serializable] // 必须添加此特性
public class People
{
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public string Birth { get; set; }
}
// 2. 序列化过程
public void BinarySerialize()
{
People people = new People()
{
Name = "吴亦凡",
Age = 18,
Sex = "男",
Birth = "2005-01-01"
};
// 创建文件流
using (FileStream fs = new FileStream("people.bin", FileMode.Create))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, people); // 将对象写入流
}
}
// 3. 反序列化过程
public void BinaryDeserialize()
{
using (FileStream fs = new FileStream("people.bin", FileMode.Open))
{
BinaryFormatter bf = new BinaryFormatter();
// 反序列化并转换为People类型
People people = bf.Deserialize(fs) as People;
Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");
}
}
特点
优点:效率高(二进制传输快)、体积小;
缺点:不可读(无法直接查看文件内容)、仅限.NET 平台(跨平台兼容性差)。
2. JSON 序列化
JSON(JavaScript Object Notation)是一种轻量级文本格式,易读易写,跨平台兼容性强(支持多语言),是目前最常用的序列化格式之一。
JSON 格式示例:
{ "Name":"吴亦凡", "Age":18, "Sex":"男", "Birth":"2005-01-01" }
方式 1:原生DataContractJsonSerializer
依赖System.Runtime.Serialization.Json命名空间,需手动标记类和属性。
使用步骤
标记类和属性:类添加
[DataContract],需序列化的属性添加[DataMember];创建文件流:指定 JSON 文件路径;
实例化序列化器:
DataContractJsonSerializer需指定对象类型(如typeof(People));序列化 / 反序列化:调用
WriteObject()(序列化)或ReadObject()(反序列化)。
示例代码
// 1. 定义数据契约类
using System.Runtime.Serialization;
[DataContract] // 标记为数据契约类
public class People
{
[DataMember] // 标记为需序列化的成员
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Sex { get; set; }
[DataMember]
public string Birth { get; set; }
}
// 2. 序列化
public void JsonSerialize_Native()
{
People people = new People()
{
Name = "吴亦凡",
Age = 18,
Sex = "男",
Birth = "2005-01-01"
};
using (FileStream fs = new FileStream("people.json", FileMode.Create))
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(People));
jsonSerializer.WriteObject(fs, people); // 写入JSON
}
}
// 3. 反序列化
public void JsonDeserialize_Native()
{
using (FileStream fs = new FileStream("people.json", FileMode.Open))
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(People));
People people = jsonSerializer.ReadObject(fs) as People; // 读取JSON并转换为对象
Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");
}
}
方式 2:第三方Newtonsoft.Json(推荐)
最流行的 JSON 处理库,简化序列化逻辑,无需标记特性,支持复杂对象和集合。
使用步骤
安装库:项目右键→“管理 NuGet 程序包”→搜索 “Newtonsoft.Json”→安装;
引入命名空间:
using Newtonsoft.Json;;序列化:调用
JsonConvert.SerializeObject(对象)生成 JSON 字符串,写入文件;反序列化:读取 JSON 字符串,调用
JsonConvert.DeserializeObject<类型>(字符串)还原对象。
示例代码
using Newtonsoft.Json;
// 1. 定义普通类(无需任何特性)
public class People
{
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public string Birth { get; set; }
}
// 2. 序列化
public void JsonSerialize_Newtonsoft()
{
People people = new People()
{
Name = "吴亦凡",
Age = 18,
Sex = "男",
Birth = "2005-01-01"
};
// 转换对象为JSON字符串
string jsonStr = JsonConvert.SerializeObject(people);
// 写入文件
File.WriteAllText("people.json", jsonStr);
}
// 3. 反序列化
public void JsonDeserialize_Newtonsoft()
{
// 读取JSON字符串
string jsonStr = File.ReadAllText("people.json");
// 转换为对象
People people = JsonConvert.DeserializeObject<People>(jsonStr);
Console.WriteLine($"姓名:{people.Name},年龄:{people.Age}");
}
JSON 序列化特点
优点:文本格式易读、跨平台(支持 Java、Python 等多语言)、第三方库使用简单;
缺点:相比二进制序列化,体积稍大、效率略低(但日常开发可忽略)。
四、三种序列化方式对比
| 序列化方式 | 核心工具类 | 可读性 | 跨平台性 | 易用性 | 适用场景 |
|---|---|---|---|---|---|
| 二进制序列化 | BinaryFormatter |
差(二进制) | 差(仅限.NET) | 中(需标记特性) | 本地高效存储、.NET 内部通信 |
| JSON 原生序列化 | DataContractJsonSerializer |
好(文本) | 好 | 中(需标记特性) | 简单跨平台数据交换 |
| JSON 第三方序列化 | Newtonsoft.Json |
好(文本) | 好 | 优(无需标记) | 多数场景(推荐),如接口通信、配置存储 |
总结
原始文本保存因依赖顺序,仅适用于极简单场景;
二进制序列化适合.NET 内部高效存储,不追求可读性时使用;
JSON 序列化(尤其是
Newtonsoft.Json)因易读、跨平台、易用,成为多数开发场景的首选。