标签:des style blog http color java 使用 os
所谓序列化,就是将对象(数据)换一种方式存储。在C#中有json序列化(JavaScriptSerializer)、Xml序列化(XmlSerializer)和二进制序列化(BinaryFormatter),因为序列化是对数据的存储,所有类中的方法、继承关系、接口它都不会存储,故序列化指的是,序列化对象中的属性(与访问修饰符无关,即便是private的属性也能被序列化,这些都是有前提的,下面会提及)还有3种形式的反序列化,下面分别给予介绍:
首先定义一个很普通的Person类:
1 public class Person 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 public string Gender { get; set; } 6 public string Telephone { get; set; } 7 }
1.json序列化(JavaScriptSerializer)
->json序列化,就是将对象序列化成一个字符串(便于对象的存储和传输)。使用步骤是先创建一个JavaScriptSerializer对象,再执行序列化:
1 //对象初始化器 2 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000" }; 3 JavaScriptSerializer jsSer = new JavaScriptSerializer(); 4 string s = jsSer.Serialize(p1); 5 Console.WriteLine(s); 6 Console.ReadKey();
运行结果如下:
->json反序列化,所谓反序列化就是序列化的逆过程,将上面代码中序列化的字符串s反序列化成Person对象。
1 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000" }; 2 JavaScriptSerializer jsSer = new JavaScriptSerializer(); 3 string s = jsSer.Serialize(p1); 4 5 //执行反序列化 6 object o = jsSer.Deserialize(s, typeof(Person)); 7 Person p2 = o as Person; 8 Console.WriteLine(string.Format("姓名是:{0},年龄:{1},性别:{2},联系电话是:{3}",p2.Name,p2.Age,p2.Gender,p2.Telephone));
运行结果如下:
2.Xml序列化(XmlSerializer)
顾名思义,xml序列化就是将对象序列化成xml格式来存储。
1 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000" }; 2 XmlSerializer xmlSer = new XmlSerializer(typeof(Person)); 3 using (FileStream fsWrite = new FileStream("person.xml", FileMode.CreateNew, FileAccess.Write)) 4 { 5 xmlSer.Serialize(fsWrite, p1); 6 } 7 Console.WriteLine("xml序列化完毕"); 8 Console.ReadKey();
运行上面的程序,弹窗后,会在执行程序集中多一个person.xml的文件,内容中数据的存储格式如下:
<?xml version="1.0"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>张三</Name> <Age>18</Age> <Gender>男</Gender> <Telephone>13800138000</Telephone> </Person>
再进行一个xml反序列化,代码如下:
1 XmlSerializer xmlSer = new XmlSerializer(typeof(Person)); 2 using (FileStream fsRead=new FileStream("person.xml",FileMode.Open,FileAccess.Read)) 3 { 4 object o = xmlSer.Deserialize(fsRead); 5 Person p2 = o as Person; 6 Console.WriteLine(string.Format("姓名是:{0},年龄:{1},性别:{2},联系电话是:{3}", p2.Name, p2.Age, p2.Gender, p2.Telephone)); 7 }
结果与json反序列化结果一致:
json序列化和xml序列化的异同点:
1.两者都是将对象以不同的格式存储;
2.json序列化是将对象序列化成字符串放在内存中;而xml序列化是将对象序列化成xml格式,并最终存储到磁盘文件中。
json反序列化和xml反序列化的异同点:
1.两者都是将序列化后的结果进行还原成原来的对象,需要注意的是,因序列化是对数据的存储,所有类中的方法、继承关系、接口它都不会存储,故序列化指的是,序列化对象中的属性(数据),反序列化也只能看到对象的数据,类中的方法、继承关系、接口等是不会在反序列化中体现的。
2.json反序列化是将json字符串“还原”成Person对象,而xml反序列化是从存储的文件中读取数据,“还原”成Person对象(反序列化后的数据都会放在内存中)。
3.二进制序列化(BinaryFormatter)
将对象(比如Person对象)转换为二进制数据(字节流)的过程。与上面2种序列化不同的是,二进制序列化要求被序列化的对象被标记为“可序列化的”(类型前加[Serializable])。
1 [Serializable] 2 public class Person 3 { 4 public string Name { get; set; } 5 public int Age { get; set; } 6 public string Gender { get; set; } 7 public string Telephone { get; set; } 8 }
二进制序列化对象的代码如下:
1 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000" }; 2 BinaryFormatter bf = new BinaryFormatter(); 3 using (FileStream fsWrite=new FileStream("1.txt",FileMode.Create,FileAccess.Write)) 4 { 5 bf.Serialize(fsWrite, p1); 6 } 7 Console.WriteLine("二进制序列化完毕"); 8 Console.ReadKey();
打开1.txt,大部分都无法看懂,依稀能看到Person类的属性。
下面看一下二进制反序列化:
1 BinaryFormatter bf = new BinaryFormatter(); 2 using (FileStream fsRead=new FileStream("1.txt",FileMode.Open,FileAccess.Read)) 3 { 4 object o = bf.Deserialize(fsRead); 5 Person p2 = o as Person; 6 Console.WriteLine(string.Format("姓名是:{0},年龄:{1},性别:{2},联系电话是:{3}", p2.Name, p2.Age, p2.Gender, p2.Telephone)); 7 } 8 Console.ReadKey();
执行结果如下:
在进行二进制反序列化时,需要注意的是,当把二进制序列化后的文件拷贝到另外一个程序中进行反序列化时,执行二进制反序列化的程序必须引用序列化文件所在的程序集,否则会报错。这是什么原因呢?是因为在进行二进制序列化时,只序列化了类中的属性,类中的其他信息:继承关系、类中的方法、接口等成员均不被序列化,引用序列化文件所在的程序集可以还原这些成员。
关于二进制序列化的一些其他问题:
1.还是上面的Person类,代码如下:
1 [Serializable] 2 public class Person 3 { 4 public car BenCi { get; set; } 5 public string Name { get; set; } 6 public int Age { get; set; } 7 public string Gender { get; set; } 8 public string Telephone { get; set; } 9 } 10 11 public class car 12 { 13 14 }
序列化代码如下:
1 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000",BenCi=new car() }; 2 BinaryFormatter bf = new BinaryFormatter(); 3 using (FileStream fsWrite = new FileStream("1.txt", FileMode.Create, FileAccess.Write)) 4 { 5 bf.Serialize(fsWrite, p1); 6 } 7 Console.WriteLine("二进制序列化完毕");
上面的代码编译没问题,运行就会报错,这是因为属性BenCi的类型car不是可序列化的,将car类标记为可序列化的即可通过。即:
1 [Serializable] 2 public class car 3 { 4 5 }
要求被序列化的对象的类型中所有属性(字段)的类型也必须标记为“可序列化的”。
2.定义一个父类,让Person类继承至它。
1 public class Animal 2 { 3 4 } 5 6 [Serializable] 7 public class Person : Animal 8 { 9 public car BenCi { get; set; } 10 public string Name { get; set; } 11 public int Age { get; set; } 12 public string Gender { get; set; } 13 public string Telephone { get; set; } 14 }
序列化代码不变:
1 Person p1 = new Person() { Name = "张三", Age = 18, Gender = "男", Telephone = "13800138000",BenCi=new car() }; 2 BinaryFormatter bf = new BinaryFormatter(); 3 using (FileStream fsWrite = new FileStream("1.txt", FileMode.Create, FileAccess.Write)) 4 { 5 bf.Serialize(fsWrite, p1); 6 } 7 Console.WriteLine("二进制序列化完毕");
运行时会报错,这是因为,虽然Person标记为可序列化的,但其父类Animal不是可序列化的。一个对象要执行序列化,不止它要标记为可序列化的,它的所有父类也必须标记为“可序列化的”,查看所有类型的父类Object,微软就将标记为Serializable,故Object是“祖宗类”,所有它的子类都可以被序列化。
3.在Person类中,如果不想让其中某个属性序列化,该怎么做呢?
1 [NonSerialized] 2 private string name = null; 3 public string Name 4 { 5 get { return this.name; } 6 set { this.name = value; } 7 }
也就是说,不参与序列化的属性不能是自动属性,要写成上面的样子,且在字段前标记为NonSerialized。这样,序列化后的结果中就不包含该属性了。
4.请看下面的代码,给Person类加下面这个方法:
1 public Animal GetAnimal(Animal ani) 2 { 3 return new Animal(); 4 }
其中Animal类并未标记为序列化,为什么编译和运行时均不会报错呢?因为序列化时类中的方法不参与序列化,所以方法的返回值和参数类型是不是可序列化的没有关系。
总结:
1.序列化,将对象换一种方式存储。
2.只序列化数据(类的属性),不序列化类中的方法。
3.一个对象要执行序列化,不止它要标记为可序列化的,它的所有父类也必须标记为“可序列化的”。
4.要求被序列化的对象的类型中所有属性(字段)的类型也必须标记为“可序列化的”。
5.类中的方法不参与序列化,所以类中的方法无需标记序列化。
6.类中的一个属性如果不想被序列化,那么要在其对应的字段前加NonSerialized.且属性不能简写。
7.反序列化时,必须找到对象序列化时原来的程序集(重新还原对象,而序列化文件中只包含哪些数据信息,不包含该对象的类型相关信息:类中有哪些方法、接口,父类是谁)。
8.序列化时,不建议用自动属性(每次生成的字段可能不一样,影响反序列化)。
标签:des style blog http color java 使用 os
原文地址:http://www.cnblogs.com/chens2865/p/3887309.html