Files
2026-05-03 14:06:26 +08:00

178 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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# 中对象持久化与数据传输的核心知识点,实际开发中需结合安全性与场景选择合适的序列化方式。