序列化 转


序列化就是将对象的状态信息转换为 可以存储或传输的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的对象写出(即保存其状态),要恢复的话则用输入流。 

原文地址:https://www.cnblogs.com/liye/p/1726981.html