為你剖解PHP序列化格式
對于那些剛剛接觸PHP語言的朋友來說,什么是PHP序列化格式可能大家都還是不太清楚。我們今天就為大家詳細(xì)講解這一方面的知識。
#t#PHP (從 PHP 3.05 開始)為保存對象提供了一組序列化和反序列化的函數(shù):serialize、unserialize。不過在 PHP 手冊中對這兩個函數(shù)的說明僅限于如何使用,而對序列化結(jié)果的格式卻沒做任何說明。
因此,這對在其他語言中實現(xiàn)PHP序列化格式來說,就比較麻煩了。雖然以前也搜集了一些其他語言實現(xiàn)的 PHP 序列化的程序,不過這些實現(xiàn)都不完全,當(dāng)序列化或反序列化一些比較復(fù)雜的對象時,就會出錯了。
于是我決定寫一份關(guān)于PHP序列化格式詳解的文檔(也就是這一篇文檔),以便在編寫其他語言實現(xiàn)的 php 序列化程序時能有一個比較完整的參考。
這篇文章中所寫的內(nèi)容是我通過編寫程序測試和閱讀 PHP 源代碼得到的,所以,我不能 100% 保證所有的內(nèi)容都是正確的,不過我會盡量保證我所寫下的內(nèi)容的正確性,對于我還不太清楚的地方,我會在文中明確指出,也希望大家能夠給予補充和完善。
PHP序列化格式后的內(nèi)容是簡單的文本格式,但是對字母大小寫和空白(空格、回車、換行等)敏感,而且字符串是按照字節(jié)(或者說是 8 位的字符)計算的,因此,更合適的說法是 PHP 序列化后的內(nèi)容是字節(jié)流格式。
因此用其他語言實現(xiàn)時,如果所實現(xiàn)的語言中的字符串不是字節(jié)儲存格式,而是 Unicode 儲存格式的話,序列化后的內(nèi)容不適合保存為字符串,而應(yīng)保存為字節(jié)流對象或者字節(jié)數(shù)組,否則在與 PHP 進(jìn)行數(shù)據(jù)交換時會產(chǎn)生錯誤。
PHP 對不同類型的數(shù)據(jù)用不同的字母進(jìn)行標(biāo)示,Yahoo 開發(fā)網(wǎng)站提供的 Using Serialized PHP with Yahoo! Web Services 一文中給出所有的字母標(biāo)示及其含義:
a - array
b - boolean
d - double
i - integer
o - common object
r - reference
s - string
C - custom object
O - class
N - null
R - pointer reference
U - unicode string
N 表示的是 NULL,而 b、d、i、s 表示的是四種標(biāo)量類型,目前其它語言所實現(xiàn)的PHP序列化格式程序基本上都實現(xiàn)了對這些類型的序列化和反序列化,不過有一些實現(xiàn)中對 s (字符串)的實現(xiàn)存在問題。
a、O 屬于最常用的復(fù)合類型,大部分其他語言的實現(xiàn)都很好的實現(xiàn)了對 a 的序列化和反序列化,但對 O 只實現(xiàn)了 PHP4 中對象序列化格式,而沒有提供對 PHP 5 中擴展的對象序列化格式的支持。
r、R 分別表示對象引用和指針引用,這兩個也比較有用,在序列化比較復(fù)雜的數(shù)組和對象時就會產(chǎn)生帶有這兩個標(biāo)示的數(shù)據(jù),后面我們將詳細(xì)講解這兩個標(biāo)示,目前這兩個標(biāo)示尚沒有發(fā)現(xiàn)有其他語言的實現(xiàn)。
C 是 PHP5 中引入的,它表示自定義的對象序列化方式,盡管這對于其它語言來說是沒有必要實現(xiàn)的,因為很少會用到它,但是后面還是會對它進(jìn)行詳細(xì)講解的。
U 是 PHP6 中才引入的,它表示 Unicode 編碼的字符串。因為 PHP6 中提供了 Unicode 方式保存字符串的能力,因此它提供了這種PHP序列化格式字符串的格式,不過這個類型 PHP5、PHP4 都不支持,而這兩個版本目前是主流,因此在其它語言實現(xiàn)該類型時,不推薦用它來進(jìn)行序列化,不過可以實現(xiàn)它的反序列化過程。在后面我也會對它的格式進(jìn)行說明。
***還有一個 o,這也是我唯一還沒弄清楚的一個數(shù)據(jù)類型標(biāo)示。這個標(biāo)示在 PHP3 中被引入用來序列化對象,但是到了 PHP4 以后就被 O 取代了。在 PHP3 的源代碼中可以看到對 o 的序列化和反序列化與數(shù)組 a 基本上是一樣的。但是在 PHP4、PHP5 和 PHP6 的源代碼中PHP序列化格式部分里都找不到它的影子,但是在這幾個版本的反序列化程序源代碼中卻都有對它的處理,不過把它處理成什么我還沒弄清楚。因此對它暫時不再作更多說明了。