C# 序列化和反序列化 详解 什么是序列化以及如何实现序列化? 如何将对象数据写入 XML 文件? 如何从 XML 文件读取对象数据?

  1. 什么是序列化以及如何实现序列化?
  2. 如何将对象数据写入 XML 文件?
  3. 如何从 XML 文件读取对象数据?

序列化是通过将对象转换为字节流,从而存储对象或将对象传输到内存,数据库或文件的过程。主要用途是保存对象的状态,包括对象的数据,以便能够在需要是重建对象。反向过程称为 反序列化。

C# 序列化和反序列化 详解
什么是序列化以及如何实现序列化?
如何将对象数据写入 XML 文件?
如何从 XML 文件读取对象数据?

如上图所示,对象 object 被序列化为 流,其中不仅包含数据、还包含对象类型的相关信息,如版本、区域性和程序集名称。然后可以将此流中的内容存储到数据库、文件或内存中。

序列化的用途:

通过序列化,可以执行如下操作:通过 Web 服务将对象发送到远程应用程序、在域之间传递对象、以 XML 字符串的形式传递对象通过防火墙、跨应用程序维护安全性或用户专属信息。

让对象可序列化:

需要具有对象、包含已序列化对象的一个流,以及一个 Fromatter。

System.Runtime.Serialization 包含序列化和反序列化对象所必须的类。

将 SerializableAttribute 特性应用于某个类型,以表示此类型的实例可以被序列化,如果对没有 SerializableAttribute 特性的类型进行序列化,则会引发异常。

如果想让类中的某个字段不可序列化,可以使用 NonSerializedAttribute 特性。

序列化的三种类型--二进制、XML、JSON

可以使用二进制 binary 或 XML 进行序列化,在 二进制序列化中,所有内容都会被序列化,且性能也很好,使用二进制编码来生成精简的序列化,可以用于基于存储或socket的网络流。

XML 序列化可提高可读性,以及对象共享和使用的灵活性,XML 序列化将对象的公共字段和属性或方法的参数和返回值序列化成符合特定 XML 格式的流,

System.Xml.Serialization 包含序列化和反序列化 XML 所需要的类

如何将对象数据写入 XML 文件?

使用 XmlSerializer 类将 overview 对象序列化并写入 XML 文件

public class XMLWrite  
{  
  
   static void Main(string[] args)  
    {  
        WriteXML();  
    }  
  
    public class Book  
    {  
        public String title;   
    }  
  
    public static void WriteXML()  
    {  
        Book overview = new Book();  
        overview.title = "Serialization Overview";  
        System.Xml.Serialization.XmlSerializer writer =   
            new System.Xml.Serialization.XmlSerializer(typeof(Book));  
  
        var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "//SerializationOverview.xml";  
        System.IO.FileStream file = System.IO.File.Create(path);  
  
        writer.Serialize(file, overview);  
        file.Close();  
    }  
}

运行结果:

在当前系统的 Documents 文件夹下生成文件 SerializationOverview.xml

内容如下图:

C# 序列化和反序列化 详解
什么是序列化以及如何实现序列化?
如何将对象数据写入 XML 文件?
如何从 XML 文件读取对象数据?

指定 XML 标签的名字

[XmlRoot(department)]
public
class Department { public string DeptName { get; set; } [XmlElement("extra")] public DeptExtraInfo DeptExtraInfo { get; set; } }

通过在 XmlRoot、XmlElement 后面加上一个括号即可实现,其中XmlRoot用于指定“根”,也就是XML的最上一层的Tag

指定 XML 标签的属性

[XmlRoot("department")]
public class Department {
    public string DeptName { get; set; } = "研发部";

    [XmlAttribute("timestamp")]
    public int Timestamp = 10;
}

Timestamp就成为了department这个根节点的timestamp属性。

去掉不需要的 namespace

默认情况下,xml 的头部会带上类似 xmlns:xsd、xmlns:xsi 的属性,不需要的化可以通过修改序列化方法实现:

    public static void WriteXML()  
    {  
        Book overview = new Book();  
        overview.title = "Serialization Overview";  
        System.Xml.Serialization.XmlSerializer writer =   
            new System.Xml.Serialization.XmlSerializer(typeof(Book));  
      XmlSerilizerNamespaces ns = new XmlSerializerNamespace();
        var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "//SerializationOverview.xml";  
        System.IO.FileStream file = System.IO.File.Create(path);  
  
        writer.Serialize(file, overview, ns);  
        file.Close();  
    }  

如何从 XML 文件读取对象数据?

使用 XmlSerializer 类读取之前写入 XML 文件的对象数据

public class Book  
{  
    public String title;  
}         
  
public void ReadXML()  
{  
    // First write something so that there is something to read ...  
    var b = new Book { title = "Serialization Overview" };  
    var writer = new System.Xml.Serialization.XmlSerializer(typeof(Book));  
    var wfile = new System.IO.StreamWriter(@"c:	empSerializationOverview.xml");  
    writer.Serialize(wfile, b);  
    wfile.Close();  
  
    // Now we can read the serialized book ...  
    System.Xml.Serialization.XmlSerializer reader =   
        new System.Xml.Serialization.XmlSerializer(typeof(Book));  
    System.IO.StreamReader file = new System.IO.StreamReader(  
        @"c:	empSerializationOverview.xml");  
    Book overview =  (Book)reader.Deserialize(file);  
    file.Close();  
  
    Console.WriteLine(overview.title);  
  
}