網站首頁 編程語言 正文
什么是序列化和反序列化:
將對象及其狀態保存起來,通常是保存到文件中,叫序列化。
將文件還原為對象,叫反序列化。
序列化和反序列化的接口和幫助類:
- 接口IFormatter
- object Deserialize(Stream serializactionStream)
- void Serialize(Stream serializationStream, object graph)
- System.Runtime.Serialization.Formatters.Binary下的BinaryFormatter,將對象序列化成二進制
- System.Runtime.Serialization.Formatters.Soap下的SoapFormatter,將對象序列化成人類可讀的文本
什么是SOAP:
Simple Object Access Protocol,簡單對象訪問協議,基于XML協議。
使用BinaryFormatter序列化對象保存到文件
using System;
using System.Data.SqlClient;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
class Program
{
static void Main(string[] args)
{
IFormatter formatter = new BinaryFormatter();
Product product = new Product(1){Price = 88.5f,Name = "Wind 850"};
Stream fs = File.OpenWrite(@"F:\product.obj");
formatter.Serialize(fs, product);
fs.Dispose();
Console.WriteLine(product);
Console.ReadKey();
}
}
[Serializable]
public class Product
{
private int id;
[NonSerialized]
private SqlConnection conn;
public Product(int id)
{
this.id = id;
this.conn = new SqlConnection(@"Data Source=.;Initial Catalog=DB;User ID=sa;Password=1");
}
public string Name { get; set; }
public double Price { get; set; }
public override string ToString()
{
return String.Format("Id:{0},Name:{1},Price:{2},conn:{3}", this.id, this.Name, this.Price,this.conn==null?"Null":"Object");
}
}
注意:
- 對象序列化需要打上[Serializable]
- 不可序列化的字段需要打上[NonSerialized],該屬性只能打在字段上
結果:
使用BinaryFormatter將文件反序列化成對象
IFormatter formatter = new BinaryFormatter();
Stream fs = File.OpenRead(@"F:\product.obj");
Product product = (Product) formatter.Deserialize(fs);
Console.WriteLine(product);
Console.ReadKey();
結果:
注意:
- 私有字段是可以反序列化的,因為反序列化的底層是通過反射來實現的,而反射是可以訪問到私有字段的。
- conn變成了null,這是因為反序列化并不會調用構造函數,而且conn本身設置成了不可以序列化。
IDeserializationCallback用來在反序列化后執行回調函數,實現沒有反序列化字段的實例化:
[Serializable]
public class Product:IDeserializationCallback
{
private int id;
[NonSerialized]
private SqlConnection conn;
public Product(int id)
{
this.id = id;
this.conn = new SqlConnection(@"Data Source=.;Initial Catalog=DB;User ID=sa;Password=1");
}
public string Name { get; set; }
public double Price { get; set; }
public override string ToString()
{
return String.Format("Id:{0},Name:{1},Price:{2},conn:{3}", this.id, this.Name, this.Price,this.conn==null?"Null":"Object");
}
public void OnDeserialization(object sender)
{
this.conn = new SqlConnection(@"Data Source=.;Initial Catalog=DB;User ID=sa;Password=1");
}
}
再次運行,得到:
使用SoapFormatter序列化對象保存到文件
IFormatter formatter = new SoapFormatter();
Product item = new Product(2){Name = "Hello world",Price = 9.5F};
Stream fs = File.OpenWrite(@"F:\product.soap");
formatter.Serialize(fs, item);
fs.Dispose();
結果:
使用SoapFormatter:
- 好處:SOAP是開放的協議,可以跨平臺的其他程序也可以使用SoapFormatter序列化的文件
- 缺點:xml文件尺寸比較大
使用序列化和反序列化事件對對象進行簡單的加密和解密
主程序:
//序列化
IFormatter formatter = new BinaryFormatter();
Product product = new Product(@"Data Source=.;Initial Catalog=DB;User ID=sa;Password=1");
Stream fs = File.OpenWrite(@"F:\product.obj");
formatter.Serialize(fs, product);
fs.Dispose();
//反序列化
Stream fs1 = File.OpenRead(@"F:\product.obj");
Product product1 = (Product)formatter.Deserialize(fs1);
Console.WriteLine(product1);
Console.ReadKey();
可序列化類:
[Serializable]
public class Product
{
private string connString;
[NonSerialized]
public SqlConnection conn;
public Product(string connString)
{
this.connString = connString;
}
[OnSerializing]
void OnSerializing(StreamingContext context)
{
Console.WriteLine("序列化前:對私有字段connString進行簡單加密");
this.connString = this.connString.Replace("a", "*");
}
[OnSerialized]
void OnSerialized(StreamingContext context)
{
Console.WriteLine("序列化后:對私有字段connString進行簡單解密");
this.connString = this.connString.Replace("*", "a");
}
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
Console.WriteLine("反序列化前:do nothing~~");
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
Console.WriteLine("反序列化后:對私有字段connString進行簡單解密,并重新初始化非序列化字段");
this.connString = this.connString.Replace("*", "a");
this.conn = new SqlConnection(connString);
}
public override string ToString()
{
return this.connString;
}
}
結果:
通過實現ISerializable接口自定義序列化過程
主要借助幫助類SerializationInfo,以鍵值對形式把需要序列化的字段或屬性保存在SerializationInfo中。另外,還需要一個反序列化時用于還原屬性值的構造函數。
[Serializable]
public class Product : ISerializable
{
private string connString;
[NonSerialized]
public SqlConnection conn;
public Product(string connString)
{
this.connString = connString;
}
//反序列化時用于還原屬性值的構造函數
protected Product(SerializationInfo info, StreamingContext context)
{
string encrypted = info.GetString("encrypted");
this.connString = encrypted.Replace("*", "a");
}
//對私有字段簡單加密以鍵值對形式保存到SerializationInfo
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
string encrypted = this.connString.Replace("a", "*");
info.AddValue("encrypted",encrypted);
}
public override string ToString()
{
return this.connString;
}
}
結果:
通過實現ISerializable接口讓沒有實現序列化的基類可被序列化
有這樣一個基類,不可以序列化。
public class ObjectBase
{
public string Name;
}
創建一個子類繼承不可以序列化的ObjectBase,并實現ISerializable接口。
[Serializable]
public class Product : ObjectBase,ISerializable
{
private string connString;
[NonSerialized]
public SqlConnection conn;
public Product(string connString)
{
this.connString = connString;
}
//反序列化時用于還原屬性值的構造函數
protected Product(SerializationInfo info, StreamingContext context)
{
string encrypted = info.GetString("encrypted");
this.connString = encrypted.Replace("*", "a");
base.Name = info.GetString("name");
}
//對私有字段簡單加密以鍵值對形式保存到SerializationInfo
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
string encrypted = this.connString.Replace("a", "*");
info.AddValue("encrypted",encrypted);
info.AddValue("name",base.Name);
}
public override string ToString()
{
return String.Format("Name:{0},Conn:{1}", base.Name, this.connString);
}
}
主程序:
//序列化
IFormatter formatter = new BinaryFormatter();
Product product = new Product(@"Data Source=.;Initial Catalog=DB;User ID=sa;Password=1"){Name = "我來自基類"};
Stream fs = File.OpenWrite(@"F:\product.obj");
formatter.Serialize(fs, product);
fs.Dispose();
//反序列化
Stream fs1 = File.OpenRead(@"F:\product.obj");
Product product1 = (Product)formatter.Deserialize(fs1);
Console.WriteLine(product1);
Console.ReadKey();
結果:
總結
- 使用BinaryFormatter:以二進制形式序列化和反序列化的時候用到。
- 使用SoapFormatter:以xml形式,或跨平臺調序列化和反序列化的時候用到。
- [NonSerialized][OnSerializing][OnSerialized][OnDeserializing]這4個事件可以對序列化和反序列化過程進行細粒度控制。
- ISerializable接口:可以把序列化字段或屬性以鍵值對形式保存在SerializationInfo中,甚至讓一個沒有序列化特性的基類實現序列化。
原文鏈接:https://www.cnblogs.com/darrenji/p/3660314.html
相關推薦
- 2022-11-12 一文搞懂Go語言中defer關鍵字的使用_Golang
- 2022-04-14 遇到一個git的大坑 src refspec master does not match any e
- 2023-11-18 Linux中ARM設備Linux 使用iperf3測量網絡帶寬
- 2022-07-06 C語言內存泄露很嚴重的解決方案_C 語言
- 2023-10-15 前端console.log打印內容與后端請求返回數據不一致
- 2022-04-03 Nginx構建Tomcat集群的操作方法_nginx
- 2023-07-05 mybatis-plus引入及其代碼生成器
- 2022-05-01 LINQ操作符SelectMany的用法_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支