Perl提供了一個Storable模塊,用來對數據結構進行序列化(serialization,Perl中稱爲凍結),也就是將數據結構保存爲二進制數據。html
Storabel的freeze和thaw函數分別用來凍結(序列化)和解凍(反序列化):網絡
#!/usr/bin/perl use 5.010; use Storable qw(freeze thaw); %hash=( 'longshuai'=>{ 'gender'=>'male', 'age' =>18, 'prov' =>'jiangxi', }, 'wugui'=>{ 'gender'=>'male', 'age' =>20, 'prov' =>'zhejiang', }, 'xiaofang'=>{ 'gender'=>'female', 'age' =>19, 'prov' =>'fujian', }, ); @name=('fairy',[qw(longshuai wugui xiaofang)]); $frozen = freeze [\%hash,\@name]; # 凍結引用,返回一個凍結後的列表 #say $frozen; # 輸出一堆亂碼 $thaw_out=thaw($frozen); # 解凍,返回引用列表 say $thaw_out->[0]; # 輸出:HASH(0x557171a4cff8) say $thaw_out->[0]{wugui}{prov}; # 輸出:zhejiang say $thaw_out->[1]; # 輸出:ARRAY(0x557171a4d220) say $thaw_out->[1][1][2]; # 輸出:xiaofang
上面的示例中,使用freeze凍結兩個數據結構後,凍結後的二進制數據內容將賦值給一個標量變量,注意它返回的是相似於字符串那種形式的,只不過這段字符串是二進制格式的。數據結構
使用thaw解凍後,將返回一個匿名列表,列表中的元素是各凍結的數據結構的引用。對於上面的示例來講,返回值相似如此結構[$ref_hash,$ref_name]
,將其賦值給一個引用變量$thaw_out
,而後就能夠經過$thaw_out->[0]
和$thaw_out->[1]
分別訪問這兩個引用。函數
以下圖描述:ui
freeze序列化過程:code
thaw反序列化過程:htm
Storable模塊能夠將數據結構序列化後持久化保存到文件中,或經過TCP套接字傳輸出去。對象
store和nstore用於將序列化數據進行持久化,它們用法同樣,以下:blog
store \%ref_hash, 'file'; store [\%ref_hash,\@ref_arr], 'file'; nstore \%ref_hash, 'file'; nstore [\%ref_hash,\@ref_arr], 'file';
可是store存儲序列化數據時默認採用的是主機字節序(host byte order),nstore默認採用的是網絡字節序(network byte order),採用網絡字節序能夠保證被TCP套接字傳輸出去時,遠程主機能以徹底一致的字節序方式讀取數據。因此,要想經過網絡傳輸序列化的對象時,須要使用nstore。dns
小知識:主機字節序和網絡字節序
多字節數據對象在存儲時,必須考慮兩個問題:
- 這段數據對象要存儲到哪一個地址
- 存儲時如何排列這些字節
這裏不考慮存儲的地址問題。對於待存儲的數值"0x1122"來講,11屬於高位字節,22屬於低位字節。對於存儲時考慮以何種字節排列方式來講,有兩種方式:大端字節序和小端字節序。假設要存儲的數據對象"0x1234567":
- 大端字節序(big-endian):存儲時,高位在前,低位在後,因此存儲的時候,和上面源數據格式同樣"01 23 45 67"
- 小端字節序(little-endian):存儲時,高位在後,低位在前,因此存儲的時候,和上面源數據格式相反"67 45 23 01"
大端字節序對人類來講比較容易理解,但幾乎全部計算機都是採用小端字節序存儲的,因此也稱爲主機字節序。而TCP/IP協議規定,網絡傳輸時的網絡字節序都採用大端字節序傳輸,這樣一來全部網絡傳輸的數據都規範化,遠程主機總會按照大端字節序去讀取傳輸過來的數據。
store和nstore持久化的序列化數據能夠經過retrieve函數讀取並反序列化。retrieve返回的值和thaw的返回結果是同樣的。
my $ref_list = retrieve 'file';
如下是nstore和retrieve的一個示例:
#!/usr/bin/perl use 5.010; use Storable qw(nstore retrieve); %hash=( 'longshuai'=>{ 'gender'=>'male', 'age' =>18, 'prov' =>'jiangxi', }, 'wugui'=>{ 'gender'=>'male', 'age' =>20, 'prov' =>'zhejiang', }, 'xiaofang'=>{ 'gender'=>'female', 'age' =>19, 'prov' =>'fujian', }, ); @name=('fairy',[qw(longshuai wugui xiaofang)]); nstore [\%hash,\@name],'/tmp/tmp_data'; # 將數據序列化並持久化到文件 $ref_list=retrieve '/tmp/tmp_data'; # 反序列化並讀取數據 say $ref_list->[0]; # 輸出:HASH(0x55aee8340318) say $ref_list->[0]{wugui}{prov}; # 輸出:zhejiang say $ref_list->[1]; # 輸出:ARRAY(0x55aee8340480) say $ref_list->[1][1][2]; # 輸出:xiaofang
下面示例涉及到文件句柄的標量引用,如不理解,請跳過。
例如,將數據結構凍結到一個字符串$string
中存儲起來:
use Storable; open my $string_fh,">",\my $string or die "...$!"; nstore_fd \@data,$string_fh; close $string_fh;
從持久化數據的變量$string
中解凍:
open my $string_fh1,"<",\$string or die "$!"; $new_hash = fd_retrieve($string_fh1); close $string_fh1;
如此,數據結構就存儲到$new_hash
這個引用中。
例如,將前文的數據結構%hash
存儲起來,並當即解凍:
#!/usr/bin/perl use Storable qw(store_fd nstore_fd fd_retrieve); use Data::Dumper; open my $string_fh,">",\my $string; nstore_fd [\%hash],$string_fh; close $string_fh; print Dumper($string); # 輸出:一大堆亂碼二進制 open my $string_fh1,"<",\$string or die "$!"; $new_hash = fd_retrieve($string_fh1); close $string_fh1; print Dumper($new_hash); # 輸出:hash數據結構
關於淺拷貝、深拷貝,見Perl的淺拷貝和深度拷貝