序列化是將變量轉換爲可保存或傳輸的字符串的過程;反序列化就是在適當的時候把這個字符串再轉化成原來的變量使用。這兩個過程結合起來,能夠輕鬆地存儲和傳輸數據,使程序更具維護性。php
這兩個是序列化和反序列化PHP中數據的經常使用函數。html
<?php $a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut'); //序列化數組 $s = serialize($a); echo $s; //輸出結果:a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";} echo '<br /><br />'; //反序列化 $o = unserialize($s); print_r($o); //輸出結果 Array ( [a] => Apple [b] => banana [c] => Coconut ) ?>
當數組值包含如雙引號、單引號或冒號等字符時,它們被反序列化後,可能會出現問題。爲了克服這個問題,一個巧妙的技巧是使用base64_encode和base64_decode。數據庫
$obj = array();
//序列化
$s = base64_encode(serialize($obj));
//反序列化
$original = unserialize(base64_decode($s)); json
可是base64編碼將增長字符串的長度。爲了克服這個問題,能夠和gzcompress一塊兒使用。數組
//定義一個用來序列化對象的函數服務器
function my_serialize( $obj )
{
return base64_encode(gzcompress(serialize($obj)));
} cookie
//反序列化
function my_unserialize($txt)
{
return unserialize(gzuncompress(base64_decode($txt)));
}函數
使用JSON格式序列化和反序列化是一個不錯的選擇: 性能
$a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
//序列化數組
$s = json_encode($a);
echo $s;
//輸出結果:{"a":"Apple","b":"banana","c":"Coconut"}測試
echo '<br /><br />';
//反序列化
$o = json_decode($s);
在上面的例子中,json_encode輸出長度比上個例子中serialize輸出長度顯然要短。
var_export 函數把變量做爲一個字符串輸出;eval把字符串當成PHP代碼來執行,反序列化獲得最初變量的內容。
$a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
//序列化數組
$s = var_export($a , true);
echo $s;
//輸出結果: array ( 'a' => 'Apple', 'b' => 'banana', 'c' => 'Coconut', )
echo '<br /><br />';
//反序列化
eval('$my_var=' . $s . ';');
print_r($my_var);
wddx_serialize_value函數能夠序列化數組變量,並以XML字符串形式輸出。
$a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
//序列化數組
$s = wddx_serialize_value($a);
echo $s;
//輸出結果(查看輸出字符串的源碼):<wddxPacket version='1.0'><header/><data><struct><var name='a'><string>Apple</string></var><var name='b'><string>banana</string></var><var name='c'><string>Coconut</string></var></struct></data></wddxPacket>
echo '<br /><br />';
//反序列化
$o = wddx_deserialize($s);
print_r($o);
//輸出結果:Array ( [a] => Apple [b] => banana 1 => Coconut )
能夠看出,XML標籤字符較多,致使這種格式的序列化仍是佔了不少空間。
上述全部的函數在序列化數組變量時都能正常執行,但運用到對象就不一樣了。例如json_encode序列化對象就會失敗。反序列化對象時,unserialize和eval將有不一樣的效果。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
PHP仍是比較經常使用的,因而我研究了一下PHP對象序列化,在這裏拿出來和你們分享一下,但願對你們有用。PHP對象序列化也是一個比較廣泛的功能,可以把一個對象進行串行化之後變成一個字符串,可以保存或者傳輸。咱們先看一個例子:
輸出結果:
咱們來分析一個對象串行化以後的字符串。
首先看對於對象自己的內容:O:9:"TestClass":2:O是說明這是一個對象類型(object),而後9是表明對象的名字查過濃度,2是表明該對象有幾個屬性。在看兩個屬性的內容:s:1:"a";s:9:"Thisisa";其實跟數組的內容比較相似,第一項:s:1:"a";是描述屬性名稱的,第二項s:9:"Thisisa";是描述屬性值的。後面的屬性相似。先說一種PHP對象序列化的應用,下面的內容是PHP手冊上,沒有更改原文。serialize()返回一個字符串,包含着能夠儲存於PHP的任何值的字節流表示。unserialize()能夠用此字符串來重建原始的變量值。用序列化來保存對象能夠保存對象中的全部變量。對象中的函數不會被保存,只有類的名稱。
要可以unserialize()一個對象,須要定義該對象的類。也就是,若是序列化了page1.php中類A的對象$a,將獲得一個指向類A的字符串幷包含有全部$a中變量的值。若是要在page2.php中將其解序列化,重建類A的對象$a,則page2.php中必需要出現類A的定義。這能夠例如這樣實現,將類A的定義放在一個包含文件中,並在page1.php和page2.php都包含此文件。
添加數據的時候,幾個一組幾個一組的狀況,總不見得每新加一組就新添加個字段,就用序列化存到字段類型爲text(我都設置爲text,由於通常不知道會出現多少個「組」)的字段中,取出時候反序列化成爲數組循環輸出就行
序列化某項的時候,會很省事,好比:form的提交,某個數據集中,由於序列化後就沒必要再在乎裏面的字符,是否是會注入等等。好處仍是不少的。
至少劣勢嘛,序列化後的字符數量要比序列化前的多,若是想放入cookie的時候須要注意長度,某些字符還須要轉義,放入到庫中的時候,由於長度不肯定,必須得用text的字段。
序列化是將變量轉換爲可保存或傳輸的字符串的過程;反序列化就是在適當的時候把這個字符串再轉化成原來的變量使用。這兩個過程結合起來,能夠輕鬆地存儲和傳輸數據,使程序更具維護性。
PHP中的序列化和反序列化分別經過函數serialize()和unserialize()便可實現。serialize()的參數能夠是resource類型外的全部變量類型,最多見的是用來序列化對象,unseialize()將serialize的返回結果做爲參數,進行反序列化,獲得原對象。
在PHP中,序列化和反序列化不少地方均可以用到!~
例如:數據庫鏈接,序列化數組等等。
數據方面:
1:升級到PHP5.5後,json,serialize,igbinary三種方式序列化後,大小沒有變化,說明這三種格式的對象結構沒有沒有變化,因此能夠無縫升級,msgpack因爲沒有以前的數據作對比,暫時未知。
2:佔用空間方面,igbinary節省空間明顯優點,好比在json一個數組5.4k大小的數據,serialize方式要8.6k,而使用igbinary方式,僅需2.4k,近乎爲serialize方式的1/4,但在小數組方面msgpack方式更具優點,igbinary佔用空間123,而msgpack方式僅爲102。可是在大數組狀況下,明顯igbinary方式優點更明顯。大數組igbinary勝出,小數組msgpack勝出。
性能方面:
1:在小數據時,json和原生serialize的性能都比PHP5.3版本有所提高,而在處理大數據量時,性能又有所降低。
2:在序列化方面,msgpack方式性能最好,其次是json_encode的,再次是igbinary,這二者相差無幾,最差的爲原生serialize,原生serialize性能消耗大概爲json和igbinary方式的的1.4倍左右,而是msgpack方式的2倍。在大數組方面,序列化方便,基本上和小數組一致,只是igbinary性能教較json_encode方式有所提高。本輪msgpack勝出。
3:在反序列方面igbinary的比序列化過程更快,固然也是最快的,可是這種快也是有成本代價的,參見最後的注意事項,最慢的爲json_decode方式,猜想緣由可能在於PHP做爲服務器端應用,最多的場景是encode,而decode的最多見的爲js處理方式,性能不是很理想。而msgpack反序列化性能基本上是它序列化的2倍。本輪igbinary勝出。
4:總體性能對比,總體性能是序列化和反序列化之和,簡單對比會發現,json是最差的,次之是原生serialize,再次爲igbinary的方式,最優的爲msgpack,不過igbinary和msgpack相差真的很是小,而在佔用空間方面,小數據時msgpack勝出,大數據時igbinary勝出,算是各有千秋。因此,若是追求極致的性能,能夠考慮使用msgpack,若是對是使用空間要求苛刻,那就選擇igbinary方式,估計這也是PHPRedis選擇igbinary做爲內置序列化方式的緣由之一,另外還有一個緣由,考慮到Redis應用場景可能是一寫多讀,要保證反序列化性能足夠高,非igbinary莫屬。
使用igbinary並不是沒有代價,在測試中咱們發現,調用igbinary_unserialize時,傳遞非法數據,會致使整個php進程死掉,日誌
估計是由於igbinary爲了提高性能,在unserialize時,沒有作相關格式驗證,致使整個進程異常退出。在使用Redis時,咱們先期使用SERIALIZE_PHP方式序列化,爲了提高性能,減小對Redis空間的浪費採用igbinary_serialize方式,再切換的時候不當心踩到這個坑,致使服務器響應出錯,直接502,幸好在daily環境上。