Files

178 lines
4.2 KiB
Markdown
Raw Permalink Normal View History

2026-05-03 14:06:26 +08:00
# C# 对象的序列化与反序列化
## 1. 什么是序列化?
**序列化(Serialization** 是指将对象的状态信息转换为可以存储或传输的形式(例如字节流、文件、内存数据)的过程。
反之,**反序列化(Deserialization)** 则是将存储或传输的序列化数据还原为对象的过程。
在 C# 中,最常用的方式是通过 `BinaryFormatter` 类来完成二进制序列化与反序列化。
---
## 2. 核心类与方法
- **BinaryFormatter.Serialize(Stream, object)**
将对象序列化到指定的流中。
- **BinaryFormatter.Deserialize(Stream)**
从指定的流中反序列化对象。
> ⚠️ 注意:从 .NET 5 开始,官方已经不推荐使用 `BinaryFormatter`(存在安全风险),更推荐 `System.Text.Json` 或 `XmlSerializer` 等。但在学习和理解基础时,仍可使用。
---
## 3. 序列化方式
### 3.1 文件流方式
通过 **文件流(FileStream** 将对象直接保存到文件中。
```
csharp
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable] // 必须标记为可序列化
public class Person
{
public string Name;
public int Age;
}
class Program
{
static void Main()
{
Person p = new Person { Name = "Tom", Age = 25 };
// 序列化到文件
using (FileStream fs = new FileStream("person.dat", FileMode.Create))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, p);
}
Console.WriteLine("对象已序列化到文件 person.dat");
}
}
```
### 3.2 内存流方式
通过 **内存流(MemoryStream** 将对象序列化成字节数组,便于网络传输或自定义存储。
```
csharp
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class Person
{
public string Name;
public int Age;
}
class Program
{
static void Main()
{
Person p = new Person { Name = "Alice", Age = 30 };
byte[] buffer;
// 序列化到内存流
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, p);
buffer = ms.ToArray(); // 获取字节数组
}
// 可以将字节数组写入文件或通过网络传输
File.WriteAllBytes("person_bytes.dat", buffer);
Console.WriteLine("对象已序列化为字节数组并写入 person_bytes.dat");
}
}
```
---
## 4. 反序列化
### 4.1 从文件反序列化
```
csharp
using (FileStream fs = new FileStream("person.dat", FileMode.Open))
{
BinaryFormatter formatter = new BinaryFormatter();
Person p = (Person)formatter.Deserialize(fs);
Console.WriteLine($"Name: {p.Name}, Age: {p.Age}");
}
```
### 4.2 从字节数组反序列化
```
csharp
byte[] buffer = File.ReadAllBytes("person_bytes.dat");
using (MemoryStream ms = new MemoryStream(buffer))
{
BinaryFormatter formatter = new BinaryFormatter();
Person p = (Person)formatter.Deserialize(ms);
Console.WriteLine($"Name: {p.Name}, Age: {p.Age}");
}
```
---
## 5. 注意事项
- **必须添加 `[Serializable]` 特性**
否则对象无法被序列化。
- **字段级别的控制**
如果某些字段不想被序列化,可以使用 `[NonSerialized]` 特性修饰。
```
csharp
[NonSerialized]
private string password;
```
- **安全问题**
`BinaryFormatter` 在反序列化时可能存在安全漏洞,不适合用于处理不受信任的数据。
- **替代方案**
- 文本序列化(如 `JsonSerializer``XmlSerializer`
- 跨平台高性能方案(如 `MessagePack``Protobuf`
---
## 6. 总结
- **文件流序列化**:直接将对象保存到磁盘文件中。
- **内存流序列化**:对象 → 字节数组 → 可保存或传输。
- **反序列化**:根据文件流或字节数组还原对象。
序列化与反序列化是 C# 中对象持久化与数据传输的核心知识点,实际开发中需结合安全性与场景选择合适的序列化方式。