之前写过一篇,但现在看来已经过时了,所以重新进行了重构
demo源码可到公众文章上百度网盘链接自取:
https://mp.weixin.qq.com/s/smm6m7gpDlUy0OjRWorP-A
一、什么是数据持久化
是指将内存中的对象数据保存到存储介质(如文件、数据库)的过程,以便后续重新读取使用。当我们关闭应用程序后,内存中的数据会丢失,而持久化技术可以确保数据长期保存。本文介绍三种实现数据持久化的方法:文本文件保存 、二进制序列化 和JSON序列化,
为什么需要数据持久化?想象一下,你要进行产品计数。如果没有持久化功能,每次程序关闭后,所有计数数据都会丢失,再次打开又是从0开始计数。而通过持久化技术,这些数据可以永久保存,方便后续查询和修改
之前写的demo在序列化部分使用了已过时且不安全的BinaryFormatter。下面是 System.Text.Json 进行重构的版本,
二、准备工作:创建项目和界面
做一个车辆生产管理的记录模块

控件名称:
车型:[txtName] 保存文本:[bitSavetxt]
生产日期:[txtManufacture] 读取文本:[btnReadtxt]
车号:[txtID] JSON序列化:[btnSerializable]
结果:[txtResult] JSON反序列化:[btnDeserializable]
三、创建数据模型类
数据模型类是持久化的基础,定义要保存数据的结构。
cs
public class Cars
{
public string Name { get; set; }
public string Result { get; set; }
public short ID { get; set; }
public DateTime Manufacture { get; set; }
}
四、方法一:文本文件保存与读取
文本文件保存是最基础的数据持久化方式,它将对象的各个属性转换为文本格式,逐行保存到文件中。
保存到文本文件
cs
private void bitSavetxt_Click(object sender, EventArgs e)
{
// 封装数据:从界面文本框获取数据并创建Cars对象
Cars objCars = new Cars()
{
Name = this.txtName.Text.Trim(),
Result = this.txtResult.Text.Trim(),
ID = Convert.ToInt16(this.txtID.Text.Trim()),
Manufacture = Convert.ToDateTime(this.txtManufacture.Text.Trim())
};
// 使用using语句自动管理资源,确保文件流正确关闭
//
try
{
using (FileStream fs = new FileStream("objCars.txt", FileMode.Create))
using (StreamWriter sw = new StreamWriter(fs))
{
// 将对象属性逐行写入文件
sw.WriteLine(objCars.Name);
sw.WriteLine(objCars.Manufacture);
sw.WriteLine(objCars.ID);
sw.WriteLine(objCars.Result);
}
MessageBox.Show("数据保存成功!");
}
catch (IOException ex) // 捕获文件操作可能出现的IOException[10](@ref)
{
MessageBox.Show($"文件操作错误:{ex.Message}");
}
catch (Exception ex) // 捕获其他异常
{
MessageBox.Show($"发生错误:{ex.Message}");
}
}
从文本文件读取
cs
// 从文本文件读取
private void btnReadtxt_Click(object sender, EventArgs e)
{
if (!File.Exists("objCars.txt"))
{
MessageBox.Show("文件不存在,请先保存数据。");
return;
}
try
{
using (FileStream fs = new FileStream("objCars.txt", FileMode.Open))
using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) // 指定编码,与写入一致
{
Cars objCars = new Cars();
// 读取并赋值,顺序必须与写入时完全一致
objCars.Name = sr.ReadLine() ?? ""; // 处理可能读取到null的情况
string manufactureString = sr.ReadLine();
string idString = sr.ReadLine();
objCars.Result = sr.ReadLine() ?? "";
// 安全地转换日期和数字
if (DateTime.TryParse(manufactureString, out DateTime manufactureDate))
{
objCars.Manufacture = manufactureDate;
}
else
{
MessageBox.Show("生产日期格式不正确,使用默认值(现在日期)。");
objCars.Manufacture = DateTime.Now; // 设置当前日期为默认值
}
if (short.TryParse(idString, out short id))
{
objCars.ID = id;
}
else
{
MessageBox.Show("编号格式不正确,无法解析,使用默认值!");
objCars.ID = 1; //设置 ID 默认值为1
}
// 将读取的数据显示在界面
this.txtName.Text = objCars.Name;
this.txtManufacture.Text = objCars.Manufacture.ToLongDateString();
this.txtID.Text = objCars.ID.ToString();
this.txtResult.Text = objCars.Result;
}
}
catch (Exception ex)
{
MessageBox.Show($"读取文件时发生错误:{ex.Message}");
}
}
文本保存优缺点:
-
优点:生成的文件人类可读,易于调试和手动修改
-
缺点:需要手动处理每个属性的保存和读取(要注意顺序),数据类型转换容易出错
五、方法二:JSON序列化(.NET官方推荐使用)
JSON序列化是最常用的方法,它生成我们可读的文本格式,且安全性高,使用System.Text.Json
库。
引入System.Text.Json命名空间
确保你的项目已引用System.Text.Json
(.NET Core 3.0+或.NET 5+以上版本默认包含,不用添加)。
JSON序列化实现
cs
private void btnSerializable_Click(object sender, EventArgs e)
{
try
{
// 封装数据
Cars objCars = new Cars()
{
Name = this.txtName.Text.Trim(),
Result = this.txtResult.Text.Trim(),
ID = Convert.ToInt16(this.txtID.Text.Trim()),
Manufacture = Convert.ToDateTime(this.txtManufacture.Text.Trim())
};
// 创建JSON序列化选项,配置缩进以便阅读
var options = new JsonSerializerOptions
{
WriteIndented = true
};
// 使用System.Text.Json将对象序列化为JSON字符串
string jsonString = JsonSerializer.Serialize(objCars, options);
// 将JSON字符串写入文件
File.WriteAllText("objCars.json", jsonString);
MessageBox.Show("JSON序列化成功!");
}
catch (Exception ex)
{
MessageBox.Show($"序列化过程中发生错误:{ex.Message}");
}
}
JSON反序列化实现
cs
private void btnDeserializable_Click(object sender, EventArgs e)
{
try
{
// 检查文件是否存在
if (!File.Exists("objCars.json"))
{
MessageBox.Show("未找到JSON文件,请先执行序列化操作。");
return;
}
// 从文件中读取JSON字符串
string jsonString = File.ReadAllText("objCars.json");
// 将JSON字符串反序列化为Cars对象
Cars objCars = JsonSerializer.Deserialize<Cars>(jsonString);
// 将数据显示在界面
this.txtName.Text = objCars.Name;
this.txtManufacture.Text = objCars.Manufacture.ToLongDateString();
this.txtID.Text = objCars.ID.ToString();
this.txtResult.Text = objCars.Result;
MessageBox.Show("JSON反序列化成功!");
}
catch (JsonException jsonEx)
{
MessageBox.Show($"反序列化失败,JSON格式错误:{jsonEx.Message}");
}
catch (Exception ex)
{
MessageBox.Show($"反序列化过程中发生错误:{ex.Message}");
}
}
六、方法三:XML序列化(备选方案)
XML序列化是另一种常用的序列化方式,特别适用于需要与旧系统交互或需要严格数据结构的场景。
XML序列化实现
cs
private void btnXmlSerialize_Click(object sender, EventArgs e)
{
try
{
// 封装数据
Cars objCars = new Cars()
{
Name = this.txtName.Text.Trim(),
Result = this.txtResult.Text.Trim(),
ID = Convert.ToInt16(this.txtID.Text.Trim()),
Manufacture = Convert.ToDateTime(this.txtManufacture.Text.Trim())
};
// 创建XmlSerializer实例
XmlSerializer serializer = new XmlSerializer(typeof(Cars));
// 序列化到文件
using (FileStream stream = new FileStream("objCars.xml", FileMode.Create))
{
serializer.Serialize(stream, objCars);
}
MessageBox.Show("XML序列化成功!");
}
catch (Exception ex)
{
MessageBox.Show($"XML序列化过程中发生错误:{ex.Message}");
}
}
XML反序列化实现
cs
private void btnXmlDeserialize_Click(object sender, EventArgs e)
{
try
{
if (!File.Exists("objCars.xml"))
{
MessageBox.Show("未找到XML文件,请先执行XML序列化操作。");
return;
}
// 创建XmlSerializer实例
XmlSerializer serializer = new XmlSerializer(typeof(Cars));
// 从XML文件反序列化
using (FileStream stream = new FileStream("objCars.xml", FileMode.Open))
{
Cars objCars = (Cars)serializer.Deserialize(stream);
// 更新界面
this.txtName.Text = objCars.Name;
this.txtManufacture.Text = objCars.Manufacture.ToLongDateString();
this.txtID.Text = objCars.ID.ToString();
this.txtResult.Text = objCars.Result;
}
MessageBox.Show("XML反序列化成功!");
}
catch (Exception ex)
{
MessageBox.Show($"XML反序列化过程中发生错误:{ex.Message}");
}
}
}
总结:
简单数据且不考虑安全的情况下,txt实现最简单,其他场景推荐JSON,XML做备选。
