zoukankan      html  css  js  c++  java
  • 序列化 转


    序列化就是将对象的状态信息转换为 可以存储或传输的Object的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从 存储区中读取或反序列化对象的状态,重新创建该对象。

    序列化是将对象状态转换为可保持或 传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

     

    序列化的目的:

    1.   以某种存储形式使自定义对象持久 化;

    2.   将对象从一个地方传递到另一个地 方。

    .NET Framework 提供两种序列化技术:

    1.   二进制序列化,保持类型保真度,这 对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、 内存和网络等等。

    2.   XML序列化,仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用 的。由于 XML 是一个开放式标准,因此,对于通过 Web 共享数据而言,这是一个很好的选择。

    下面使用BinaryFormatter序列化类Book作为例子来体会什么是序列化。

     

    定义类Book:

    [Serializable]
    public class Book
    {
        string name;
        float price;
        string author;

    public Book(string bookname, float bookprice, string bookauthor)
        {
         name = bookname;
         price = bookprice;
         author = bookauthor;
        }
    }

     

    在类的上面增加了属性Serializable(如果不加这个属性,将抛出SerializationException异常)。通过这个属性将Book标志为可以序列化的。当然也有另一种 方式使类Book可以序列化,那就是实行ISerializable接口了。NoteSerializable属性是不能被继承的。

     

    如果你不想序列化某个变量,该怎么 处理呢?很简单,在其前面加上属性[NonSerialized]。比如我不想序列化

    string author;

    那我只需要

    [NonSerialized]

    string author;

     

    接下来就是见证如何序列化的时刻:

    using System;

    using System.IO;

    using System.Runtime.Serialization.Formatters.Binary;

    首先创建Book实例,like this:  

    Book book = new Book("Day and Night", 30.0f, "Bruce");

    接着当然要创建一个文件了,这个文件就是用来存放我们要序列化的信息了。

    FileStream fs = new FileStream(@"C:\book.dat", FileMode.Create);

    序列化的实现也很简单,like this

          BinaryFormatter formatter = new BinaryFormatter();
          formatter.Serialize(fs, book);

     

    完整代码如下:

    static void Main(string[] args)

    {
         Book book = new Book("Day and Night", 30.0f, "Bruce");

         using(FileStream fs = new FileStream(@"C:\book.dat", FileMode.Create))
         {
              BinaryFormatter formatter = new BinaryFormatter();
              formatter.Serialize(fs, book);
         }

         book = null;

         using(FileStream fs = new FileStream(@"C:\book.dat", FileMode.Open))
         {
              BinaryFormatter formatter = new BinaryFormatter();
              book = (Book)formatter.Deserialize(fs);//
    这里返回值是object
         }
    }

    序列化 (serialization)
    将对象的状态信息转换为可以存储或传输的窗体的过程。在序列化期间,对 象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
    序列化使其他代码可以查 看或修改那些不序列化便无法访问的对象实例数据。确切地说,代码执行序列化需要特殊的权限:即指定了 SerializationFormatter 标志的 SecurityPermission。在默认策略下,通过 Internet 下载的代码或 Intranet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。
    通常,对象实例的所有字段都会被序列化,这意味着数据会被表示为实例的序列 化数据。这样,能够解释该格式的代码有可能能够确定这些数据的值,而不依赖于该成员的可访问性。类似地,反序列化从序列化的表示形式中提取数据,并直接设 置对象状态,这也与可访问性规则无关。
    对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列 化的,请尝试生成特定字段来保存不可序列化的重要数据。如果无法实现这一点,则应注意该数据会被公开给任何拥有序列化权限的代码,并确保不让任何恶意代码 获得该权限。
    .NET Framework 提供两种序列化技术:
        * 二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。 您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。
        * XML 序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用的。由于 XML 是一个开放式标准,因此,对于通过 Web 共享数据而言,这是一个很好的选择。SOAP 同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。
    下面是一个序列化的例子:摘自于MSDN
    该程序运行在Console应用程序下:

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    namespace Microsoft.Samples.CustomOrder
    {
        public class OrderedClass
        {
            private int field1;
            private string field2;
            private string field3;
            [XmlElement(Order = 3)]
            public string Field3
            {
                get { return field3; }
                set { field3 = value; }
            }
            [XmlElement(Order = 1)]
            public int Field1
            {
                get { return field1; }
                set { field1 = value; }
            }
            [XmlElement(Order = 2)]
            public string Field2
            {
                get { return field2; }
                set { field2 = value; }
            }
            public OrderedClass()
            {
                field1 = 1;
                field2 = "String1";
                field3 = "String2";
            }
        }
        public class UnorderedClass
        {
            private int field1;
            private string field2;
            private string field3;
            public string Field3
            {
                get { return field3; }
                set { field3 = value; }
            }
            public int Field1
            {
                get { return field1; }
                set { field1 = value; }
            }
            public string Field2
            {
                get { return field2; }
                set { field2 = value; }
            }
            public UnorderedClass()
            {
                field1 = 1;
                field2 = "String1";
                field3 = "String2";
            }
        }
        static class Program
        {
            static void Main()
            {
                UnorderedClass unordered = new UnorderedClass();
                OrderedClass ordered = new OrderedClass();
                XmlSerializer unorderedSerializer =
                    new XmlSerializer(typeof(UnorderedClass));
                XmlSerializer orderedSerializer =
                    new XmlSerializer(typeof(OrderedClass));
                Console.WriteLine("Unordered serialization:\n");
                unorderedSerializer.Serialize(Console.Out, unordered);
                Console.WriteLine("\n\nOrdered serialization:\n");
                orderedSerializer.Serialize(Console.Out, ordered);
                Console.ReadLine();
            }
        }
    }
     

    简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行 读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来 解决这些问题的!

    问题的引出:

    如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子 来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为 对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个 空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所 希望的!

    以下序列化机制的解决方案:

    1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)

    2.当要保存一个对象时,先检查该对象是否被保存了。

    3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象

    通过以上的步骤序列化机制解决了对象引用的问题!

    序列化的实现

    将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。 

  • 相关阅读:
    bzoj 1022: [SHOI2008]小约翰的游戏John anti_nim游戏
    spoj gss2 : Can you answer these queries II 离线&&线段树
    hduoj 1077 Catching Fish 求单位圆最多覆盖点个数
    HDUOJ Clear All of Them I 状压DP
    bzoj 1013: [JSOI2008]球形空间产生器sphere 高斯消元
    bzoj 1006: [HNOI2008]神奇的国度 弦图的染色问题&&弦图的完美消除序列
    Cocos2d-x Lua中生命周期函数
    Cocos2d-x Lua中使用标签
    Cocos2d-x Lua中Sprite精灵类
    Cocos2d-x Lua Node与Node层级架构
  • 原文地址:https://www.cnblogs.com/liye/p/1726981.html
Copyright © 2011-2022 走看看