序列化与反序列化对象

应用程序常常需要在硬盘上存储数据。之前介绍了逐段构建文本和数据文件,但这常常不是最简便的方式。有时最好以对象形式存储数据。

.NET Framework 在System.Runtime.Serialization 和System.Runtime.Serialization.Formatters名称空间中提供了序列化对象的基础架构,这两个名称空间中的一些类实现了这个基础架构。Framework中有两个可用的实现方式:

1)System.Runtime.Serialization.Formatters.Binary:这个名称空间包含了BinaryFormatter 类,它能把对象序列化为二进制数据,把二进制数据序列化为对象。

2)System.Runtime.Serialization.Formatters.Soap:这个名称空间包含了SoapFormatter 类,它能把对象序列化为SOAP 格式的XML 数据,把SOAP 格式的XML 数据序列化为对象。

IFormatter 接口提供了如下方法:

void Serialize(Stream stream, object source) 把source 序列化为stream

object Deserialize(Stream stream) 反序列化stream 中的数据,返回得到的对象

看一个栗子:

namespace ObjectStore

{

//要先标记“可序列化”

[Serializable]

public class Product

{

public long Id;

public string Name;

public double Price;

//任何成员都可以用这个特性标记,但不能和其他成员一起存储。如果只有一个字段或属性包含敏感数据,这就是很有用的。

[NonSerialized]

string Notes;

public Product(long id, string name, double price, string notes)

{

Id = id;

Name = name;

Price = price;

Notes = notes;

}

public override string ToString()

{

return string.Format("{0}: {1} (${2:F2}) {3}", Id, Name, Price, Notes);

}

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

static void Main(string[] args)

{

try

{

// Create products.

List<Product> products = new List<Product>();

products.Add(new Product(1, "Spiky Pung", 1000.0, "Good stuff."));

products.Add(new Product(2, "Gloop Galloop Soup", 25.0, "Tasty."));

products.Add(new Product(4, "Hat Sauce", 12.0, "One for the kids."));

Console.WriteLine("Products to save:");

foreach (Product product in products)

{

Console.WriteLine(product);

}

Console.WriteLine();

// Get serializer.

IFormatter serializer = new BinaryFormatter();

// Serialize products.

FileStream saveFile =

new FileStream("Products.bin", FileMode.Create, FileAccess.Write);

serializer.Serialize(saveFile, products);

saveFile.Close();

// Deserialize products.

FileStream loadFile =

new FileStream("Products.bin", FileMode.Open, FileAccess.Read);

List<Product> savedProducts =

serializer.Deserialize(loadFile) as List<Product>;

loadFile.Close();

Console.WriteLine("Products loaded:");

foreach (Product product in savedProducts)

{

Console.WriteLine(product);

}

}

catch (SerializationException e)

{

Console.WriteLine("A serialization exception has been thrown!");

Console.WriteLine(e.Message);

}

catch (IOException e)

{

Console.WriteLine("An IO exception has been thrown!");

Console.WriteLine(e.ToString());

}

Console.ReadKey();

}

我们常常需要存储和检索表示对象状态的数据。可以使用序列化技术来自动保存和加载对象状态,而无需编写代码来保存和加载属性值。为此,必须使用Serializable 特性把对象类型标记为可序列化,还可以使用其他属性控制如何序列化成员,例如NonSerialized 特性禁止序列化给的成员。

拓展:

常见数据结构在内存中是怎么存储的:

在开发中,经常用到数组,ArrayList,HashMap等,他们在内存中是怎么存储的呢?其实在他们在申请内存时,要么是一块连续的内存,要么是分散的,要么是结合使用。说白了在底层存储结构只有两种:数组和链表;数组是连续的,只要知道了首地址,就可以通过步长访问数组内所有的值,如arraylist是基于数组的。链表是分散的,每个位置除了包含值还会包含下一项的指针,双向链表会前后两项的指针。

1)ArrayList底层是基于数组存储的,相对于数组,arraylist可以动态扩容(使用数组时,在定义时,需要指定长度,但arrayList不需要,arrayList是动态扩容的)。所以arrayList中存储是连续的,查询会很方便。但删除插入时,除非是尾部,否则都会涉及到其他位置的重新赋值,影响效率。

2)Hashmap 是基于数组和链表的,hashMap 默认申请大小为16 的数组,当存储时,根据key的hashCode,决定存储在数组中的第几个索引,如果该索引已经存储了其他元素,刚判断两个key是否相等,如果相等,刚覆盖,否则存储在该索引处的链表中。hashMap扩容时,也需要重新申请一块连续的内存,将原内存块内容复制到新的内存块中,但是个索引处的链表节点,不需要重新创建。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值