-
序列化
鎖定
序列化 (Serialization)是將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。在序列化期間,對象將其當前狀態寫入到臨時或持久性存儲區。以後,可以通過從存儲區中讀取或反序列化對象的狀態,重新創建該對象。
序列化使其他代碼可以查看或修改那些不序列化便無法訪問的對象實例數據。確切地説,代碼執行序列化需要特殊的權限:即指定了 SerializationFormatter 標誌的 SecurityPermission。在默認策略下,通過 Internet 下載的代碼或 Internet 代碼不會授予該權限;只有本地計算機上的代碼才被授予該權限。
通常,對象實例的所有字段都會被序列化,這意味着數據會被表示為實例的序列化數據。這樣,能夠解釋該格式的代碼有可能能夠確定這些數據的值,而不依賴於該成員的可訪問性。類似地,反序列化從序列化的表示形式中提取數據,並直接設置對象狀態,這也與可訪問性規則無關。
對於任何可能包含重要的安全性數據的對象,如果可能,應該使該對象不可序列化。如果它必須為可序列化的,請嘗試生成特定字段來保存不可序列化的重要數據。如果無法實現這一點,則應注意該數據會被公開給任何擁有序列化權限的代碼,並確保不讓任何惡意代碼獲得該權限。
- 中文名
- 序列化
- 外文名
- Serialization
- 類 型
- 概念
- 類 別
- 通信
目錄
- 1 目的
- 2 技術
- 3 Java編程中的序列化
序列化目的
1、以某種存儲形式使自定義對象持久化;
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
注: 在 php 3 中,在序列化和解序列化的過程中對象會失去類的關聯。結果的變量是對象類型,但是沒有類和方法,因此就沒什麼用了(就好像一個用滑稽的語法定義的數組一樣)。
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。