序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
序列化使其他代码可以查看或修改那些不序列化便无法访问的对象实例数据。确切地说,代码执行序列化需要特殊的权限:即指定了 SerializationFormatter 标志的 SecurityPermission。在默认策略下,通过 Internet 下载的代码或 Internet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。
通常,对象实例的所有字段都会被序列化,这意味着数据会被表示为实例的序列化数据。这样,能够解释该格式的代码有可能能够确定这些数据的值,而不依赖于该成员的可访问性。类似地,反序列化从序列化的表示形式中提取数据,并直接设置对象状态,这也与可访问性规则无关。
对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列化的,请尝试生成特定字段来保存不可序列化的重要数据。如果无法实现这一点,则应注意该数据会被公开给任何拥有序列化权限的代码,并确保不让任何恶意代码获得该权限。
- 中文名
- 序列化
- 外文名
- Serialization
- 类 型
- 概念
- 类 别
- 通信
目录
目的
播报编辑
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性。
技术
播报编辑
* 二进制虹辣归序列化保持类型保真度,这对于在应用程序的不同调用之间保留对渗危禁永象的状态很有用。例厦体甩如,通过将对榆请屑象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在踏局坑计算机或应用程序域之间传递对象。
* XML 序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一辩墓档点是很有用的。由于 XML 是一个开放式标准芝海,因此,对于通过 Web 共享数据而照坑言,这是一个很好的选择。SOAP 同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。
Java编程中的序列化
播报编辑
序列化的实现方法
把一个Java对象写入到硬盘或者传输到网络上面的其它计算机,这时我们就需要自己去通过java把相应的对象写成转换成字节流。对于这种通用的操作,我们为什么不使用统一的格式呢?没错,这里就出现了java的序列化的概念。在Java的OutputStream类下面的子类ObjectOutputStream类就有对应的WriteObject(Object object) 其中要求对应的object实现了java的序列化的接口。
在使用tomcat开发JavaEE相关项目的时候,我们关闭tomcat后,相应的session中的对象就存储在了硬盘上,如果我们想要在tomcat重启的时能够从tomcat上面读取对应session中的内容,那么保存在session中的内容就必须实现相关的序列化操作,还有jdbc加载驱动用的就是反序列化,将字符串变为对象。
序列化操作
public class Book implements Serializable{
//序列化类:java.ioObjectOutputStream将对象变为指定的二进制数据
private static final long serialVersionUID = 1L;
private String title;
private double price;
public Book(String tit,double pri){
this.title=tit;
this.price=pri;
}
public String toString() {
Map<String, String> hashMap = new HashMap<String, String>();
hashMap.put("Computer base", "6.2");
hashMap.put("Computer webpage", "45.2");
hashMap.put("Java", "105.2");
hashMap.put("Andriod", "89.2");
//第一种:使用keySet()方法遍历哈希表hashMap中的一些元素
System.out.println("通过keySet()方法遍历key和value:");
Set<String> keys = hashMap.keySet();
for (String key : keys) {
String value= hashMap.get(key);
System.out.println("BookName:"+ key + " ,BookPrice:" + value);
}
return "BookName:"+this.title+" ,BookPrice:"+this.price;
}
}
反序列化
public class Serialization {
public static File file = null;
public static void main(String[] args) throws Exception, IOException {
file = new File("serialize.doc");
//序列化到指定的文本
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(new Book("Java Development",45.3));
oos.flush();
oos.close();
file = new File("serialize.doc");
//反序列化到指定的文本
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
Object obj=ois.readObject();
Book book=(Book) obj;
System.out.println("\n By using the byte stream serialization operation, "
+ "we can see the following information:\n"+book);
ois.close();
}
}
无序列化
类某些属性不需要序列化,以上序列化和反序列化实现了的对象序列化,但是可以发现,操作时是将整个对象的所有属性序列化,那么transient关键字可以将某些内容不需要保存,就可以通过transient关键字来定义:private transient String title;此时title属性无法被序列化
C#编程中的序列化
播报编辑
using System;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;//二进制序列化
using System.Runtime.Serialization.Formatters.Soap;//SOAP序列化
using System.Xml.Serialization;//XML序列化
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//如果要想保存某个class中的字段,必须在class前面加个这样[Serializable]
[Serializable]
public class Person
{
public int age;
public string name;
[NonSerialized] //如果某个字段不想被保存,则加个这样的标志
public string secret;
}
//序列化
private void btnXlh_Click(object sender, EventArgs e)
{
Person person = new Person();
person.age = 28;
person.name = "Hoam\r\n";
person.secret = "no look";
string str = System.AppDomain.CurrentDomain.BaseDirectory;
//二进制序列化
FileStream streamHx = new FileStream(str+"personHx.txt", FileMode.Create);
BinaryFormatter bFormatHx = new BinaryFormatter();
bFormatHx.Serialize(streamHx, person);
streamHx.Close();
//SOAP序列化
FileStream streamSoap = new FileStream(str + "personSoap.xml", FileMode.Create);
SoapFormatter bFormatSoap = new SoapFormatter();
bFormatSoap.Serialize(streamSoap, person);
streamSoap.Close();
//XML序列化 //某个字段加[NonSerialized]标志不起作用,仍被保存
FileStream streamXml = new FileStream(str+ "personXml.xml", FileMode.Create);
XmlSerializer xmlserilize = new XmlSerializer(typeof(Person));
xmlserilize.Serialize(streamXml, person);
streamXml.Close();
}
//反序列化
private void btnFxlh_Click(object sender, EventArgs e)
{
Person person = new Person();
string str = System.AppDomain.CurrentDomain.BaseDirectory;
object data;
//二进制反序列化
FileStream streamHx = new FileStream(str + "personHx.txt", FileMode.OpenOrCreate);
BinaryFormatter bFormatHx = new BinaryFormatter();
data = bFormatHx.Deserialize(streamHx); //反序列化得到的是一个object对象.须做下类型转换
streamHx.Close();
//SOAP反序列化
FileStream streamSoap = new FileStream(str + "personSoap.xml", FileMode.OpenOrCreate);
SoapFormatter bFormatSoap = new SoapFormatter();
data = bFormatSoap.Deserialize(streamSoap); //反序列化得到的是一个object对象.须做下类型转换
streamSoap.Close();
//XML反序列化
FileStream streamXml = new FileStream(str + "personXml.xml", FileMode.OpenOrCreate);
XmlSerializer xmlserilize = new XmlSerializer(typeof(Person));
data = xmlserilize.Deserialize(streamXml); //反序列化得到的是一个object对象.须做下类型转换
streamXml.Close();
}
}
}
PHP
播报编辑
serialize() 返回一个字符串,包含着可以储存于 php 的任何值的字节流表示。unserialize() 可以用此字符串来重建原始的变量值。用序列化来保存对象可以保存对象中的所有变量。对象中的函数不会被保存,只有类的名称。
要能够 unserialize() 一个对象,需要定义该对象的类。也就是,如果序列化了 page1.php 中类 A 的对象 $a,将得到一个指向类 A 的字符串并包含有所有 $a 中变量的值。如果要在 page2.php 中将其解序列化,重建类 A 的对象 $a,则 page2.php 中必须要出现类 A 的定义。例如可以这样实现,将类 A 的定义放在一个包含文件中,并在 page1.php 和 page2.php 都包含此文件。
<?php// classa.inc: class A { var $one = 1; function show_one() { echo $this->one; } }// page1.php: include("classa.inc"); $a = new A; $s = serialize($a); // 将 $s 存放在某处使 page2.php 能够找到 $fp = fopen("store", "w"); fwrite($fp, $s); fclose($fp);// page2.php: // 为了正常解序列化需要这一行 include("classa.inc"); $s = implode("", @file("store")); $a = unserialize($s); // 可以用 $a 对象的 show_one() 函数了 $a->show_one();?>
如果在用会话并使用了 session_register() 来注册对象,这些对象会在每个 php 页面结束时被自动序列化,并在接下来的每个页面中自动解序列化。基本上是说这些对象一旦成为会话的一部分,就能在任何页面中出现。
强烈建议在所有的页面中都包括这些注册的对象的类的定义,即使并不是在所有的页面中都用到了这些类。如果没有这样做,一个对象被解序列化了但却没有其类的定义,它将失去与之关联的类并成为 stdClass 的一个对象而完全没有任何可用的函数,这样就很没有用处。
因此如果在以上的例子中 $a 通过运行 session_register("a") 成为了会话的一部分,应该在所有的页面中包含 classa.inc 文件,而不只是 page1.php 和 page2.php。