Perl數據序列化和持久化(入門):Storable模塊

Perl提供了一個Storable模塊,用來對數據結構進行序列化(serialization,Perl中稱爲凍結),也就是將數據結構保存爲二進制數據。html

  • 序列化後的數據能夠寫入文件實現持久化,能夠將持久化文件拷貝給遠程機器
  • 也能夠經過網絡套接字將序列化數據傳遞給遠程機器
  • 序列化後的數據在任意機器上均可以反序列化(deserialization,Perl中稱爲解凍)獲得原始的數據結構
  • 序列化數據結構時是進行深拷貝的,序列化完成後,修改原始數據,不會影響反序列化的結果

序列化:freeze、nfreeze和thaw

Storabel的freeze和thaw函數分別用來凍結(序列化)和解凍(反序列化):網絡

  • freeze凍結的是數據對象,不包括它們的引用和名稱
  • freeze的參數須要是引用,能夠是多個引用參數,返回的是二進制的凍結序列,各數據結構序列化在不一樣行
  • thaw的參數是引用變量,返回的是一個匿名列表,列表各元素對應freeze凍結時的各數據結構
  • nfreeze也是凍結,可是按照網絡字節序進行序列化,適合遠程傳輸序列化時的標量名稱,見下一小節對主機字節序和網絡字節序的描述
#!/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

持久化:store、nstore和retrieve

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

序列化到文件描述符:store_fd、nstore_fd和fd_retrieve

  • store_fd、nstore_fd用於將數據結構凍結到指定的文件描述符,好比文件、管道、套接字、字符串中
  • retrieve_fd則從給定的文件描述符中讀取

下面示例涉及到文件句柄的標量引用,如不理解,請跳過。

例如,將數據結構凍結到一個字符串$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數據結構

深拷貝:dclone

關於淺拷貝、深拷貝,見Perl的淺拷貝和深度拷貝

相關文章
相關標籤/搜索