zoukankan      html  css  js  c++  java
  • C# 序列化

         所谓序列化,就是将对象(数据)换一种方式存储。在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.序列化时,不建议用自动属性(每次生成的字段可能不一样,影响反序列化)。

  • 相关阅读:
    cordova环境配置
    2016年读书计划
    红皇后假说
    微信OAuth2.0网页授权
    2016年碎语
    Apache + PHP 环境搭建
    各种环境配置
    技术名词记
    使用新浪云(SAE)实现基于mySql和微信公众平台的关键字请求响应服务
    为什么安装office后,xls文件不显示excel图标
  • 原文地址:https://www.cnblogs.com/chens2865/p/3887309.html
Copyright © 2011-2022 走看看