Perl提供了一个Storable模块,用来对数据结构进行序列化(serialization,Perl中称为冻结),也就是将数据结构保存为二进制数据。

  • 序列化后的数据可以写入文件实现持久化,可以将持久化文件拷贝给远程机器
  • 也可以通过网络套接字将序列化数据传递给远程机器
  • 序列化后的数据在任意机器上都可以反序列化(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]分别访问这两个引用。

如下图描述:

freeze序列化过程:

thaw反序列化过程:

持久化:store、nstore和retrieve

Storable模块可以将数据结构序列化后持久化保存到文件中,或通过TCP套接字传输出去。

store和nstore用于将序列化数据进行持久化,它们用法一样,如下:

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。

小知识:主机字节序和网络字节序

多字节数据对象在存储时,必须考虑两个问题:

  • 这段数据对象要存储到哪个地址
  • 存储时如何排列这些字节

这里不考虑存储的地址问题。对于待存储的数值"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的浅拷贝和深度拷贝

Perl数据序列化和持久化(入门):Storable模块的更多相关文章

  1. 常用模块(数据序列化 json、pickle、shelve)

    本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...

  2. json&pickle数据序列化模块

    用于序列化的模块 json,通用的序列化方式,序列化成为str类型,支持所有语言识别,序列化的数据具有局限性. pickle,python的所有数据类型都可以被序列化,序列化为bites格式,只适用于 ...

  3. Python之数据序列化(json、pickle、shelve)

    本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...

  4. Python全栈之路----常用模块----序列化(json&pickle&shelve)模块详解

    把内存数据转成字符,叫序列化:把字符转成内存数据类型,叫反序列化. Json模块 Json模块提供了四个功能:序列化:dumps.dump:反序列化:loads.load. import json d ...

  5. 【转】Python之数据序列化(json、pickle、shelve)

    [转]Python之数据序列化(json.pickle.shelve) 本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型 ...

  6. python 数据序列化(json、pickle、shelve)

    本来要查一下json系列化自定义对象的一个问题,然后发现这篇博客(https://www.cnblogs.com/yyds/p/6563608.html)很全面,感谢作者,关于python序列化的知识 ...

  7. 数据序列化导读(2)[YAML]

    上一节讲了JSON, 这一节将介绍YAML.可以认为,YAML是JSON的超集,但是更加简单易用,适合人类阅读和书写. 1.  什么是YAML? YAML是YAML Ain't Markup Lang ...

  8. JAVA的序列化和持久化的区别与联系

      持久化(Persistence) 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中.XML数据文 ...

  9. spark新能优化之序列化的持久化级别

    除了对多次使用的RDD进行持久化操作之外,还可以进一步优化其性能.因为很有可能,RDD的数据是持久化到内存,或者磁盘中的.那么,此时,如果内存大小不是特别充足,完全可以使用序列化的持久化级别,比如ME ...

随机推荐

  1. ps最最基础的文档

    因为学习PHP,但是公司没有前端工程师,修图的时候只好找被人帮忙,一个简答的问题,其实几分钟就搞定了,还要麻烦别人,就自己学了一下ps.一共花了3天时间.学习了一些简单的操作. 工具:Adobe Ph ...

  2. idea 中dao层自动生成接口

    1.在生成接口的类上右键 2.选中要生成的接口方法 3.点击Yes 4.出现(? reference in ? file)即生成成功

  3. OC基础成员变量、属性变量、实例方法与类方法

    首先,为什么我们要定义一个新类呢?按照我的理解,就是为了抽象出来一个新的东西(也就是类),用来存储更多的数据变量和方法,一切类都直接或间接继承与NSObject. 在类的头文件里我们可以定义成员变量. ...

  4. 【高速接口-RapidIO】3、RapidIO串行物理层的包传输过程

    一.引言 前几篇文章已经谈到RapidIO的协议,串行物理层与控制符号. RapidIO协议包括读事务(NREAD),写事务(NWRITE),流写事务(SWRITE),有响应的写事务(NWRITE_R ...

  5. 小程序开发基础-scroll-view 可滚动视图区域

    小编 / 达叔小生 小程序开发基础-scroll-view 可滚动视图区域 这里只展示纵向滚动,横向同理就不用说明了,可自己尝试,横向滚动属性为scroll-x,把纵向滚动改为横向滚动即可. scro ...

  6. 控制页面打印的2种方法(css3的media媒体查询和window.print())

    在实际开发中,有时可能会有打印的需求.下面我总结了2种打印的方法,希望对各位小伙伴有所帮助. ①:直接用window.print()方法就可以打印整个页面,下面是一个小demo <!DOCTYP ...

  7. Redis 设计与实现 (一)--数据结构

    底层数据结构:动态字符串.字典.整数集合.双端链表.压缩列表 字符串对象: int    浮点数值 raw  字符串值>32字节 embstr   字符串值<32字节 字符串编码转换: i ...

  8. 远程桌面连接:出现身份验证错误,要求的函数不受支持,可能是由于CredSSP加密Oracle修正的解决方法

    在做app时需要连接服务器来进行数据交互,但是在阿里云页面里连接服务器太不好用,所以使用windows自带的远程连接来进行. 一.但是连接的过程中出现了以下问题: 二.最初是有点迷茫的,不知道从哪里下 ...

  9. 大道至简第一章--java伪代码读后感

    import java.大道至简.编程的精义; //愚公移山 public class 愚公移山 { public static void main(String[] args) { //惩山北之塞, ...

  10. Xamarin.Android 上中下布局

    xml代码: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...