序列化/反序列化

序列化(串行化):将变量转换为可保存或传输的字符串的过程;

反序列化(反串行化):在适当的时候把这个字符串再转化成原来的变量使用。

序列化和反序列化是编程中用于处理数据对象转换过程的关键技术,它们具有以下重要作用和解决的核心问题:

1.数据持久化:

    作用:将内存中的对象状态转换为易于存储(如磁盘文件、数据库记录)的格式,以便在需要时恢复对象状态。

    解决的问题:应用程序关闭或重启时,内存中的对象状态会丢失。通过序列化,可以将对象状态持久化到非易失性存储介质中,确保在程序重启后仍能恢复到之前的状态。这对于用户会话管理(如登录状态、购物车内容)、游戏存档、配置数据等应用场景至关重要。

2.网络传输:

    作用:将对象序列化为字节流,便于在网络间高效、安全地传输。

    解决的问题:网络通信只能传输二进制数据。序列化将复杂的对象结构和数据类型转换为统一的字节流格式,便于在网络中发送和接收。接收端通过反序列化将字节流还原为与发送端一致的对象结构,实现了跨进程、跨机器甚至跨网络环境的数据交换,这对于分布式系统、远程调用(如RPC)、Web服务(如REST API)等场景必不可少。

3.进程间通信(IPC):

    作用:在多个进程或线程之间传递对象状态。

    解决的问题:不同进程有自己的独立内存空间,无法直接访问对方的内存对象。通过序列化,可以将对象转化为可以在进程间共享的数据格式(如管道、消息队列、共享内存等),使得不同进程间能够传递复杂数据结构。反序列化则在接收端重建对象,实现跨进程的数据同步和协作。

4.缓存:

    作用:将计算结果或复杂数据结构存储在高速缓存中,以提高后续访问速度。

    解决的问题:某些计算密集型或资源消耗大的操作产生的结果,如果频繁请求,直接重新计算会浪费时间和系统资源。通过序列化将结果对象存储在缓存(如Redis、Memcached)中,后续请求可以直接反序列化获取,显著提升应用性能。

5.数据备份与恢复:

    作用:将关键业务数据或系统状态以序列化形式备份,用于灾难恢复或数据迁移。

    解决的问题:系统故障、硬件损坏或数据丢失可能导致业务中断。定期将重要对象序列化并备份至安全位置,能够在发生问题时快速恢复数据和系统状态,保证业务连续性。

6.兼容性与互操作性:

    作用:不同编程语言或系统之间通过标准的序列化格式(如JSON、XML、Protocol Buffers等)交换数据。

    解决的问题:不同技术栈之间往往存在语言差异和数据模型差异。序列化提供了一种通用的数据交换格式,使得不同系统、平台或语言编写的组件能够理解和处理彼此的数据,实现跨语言、跨平台的互操作。

总结来说,序列化和反序列化主要用于解决以下几个核心问题:

数据持久化:跨越程序运行周期,保持对象状态。

网络通信:在不同系统间高效、安全地传输对象数据。

进程间通信:在不同进程间共享对象状态。

缓存机制:快速访问先前计算结果或复杂数据。

数据备份与恢复:确保业务连续性和数据安全性。

兼容性与互操作性:实现跨语言、跨平台的数据交换。

示例:

<?php

$data = array('pig', 'tiger', 'elephant');
 
// 序列化数据
$serialized = serialize($data);
echo $serialized;
echo "<br>";
// 反序列化数据
$unserialized = unserialize($serialized);
print_r($unserialized);

?>

第一段输出中每一个字符分别代表:

a: 表示这是一个数组(array)。

3: 表示这是一个包含3个元素的数组

i: 代表整数(integer),通常用于表示数组的索引值。

s: 代表字符串(string),在这里用于表示数组元素的取值。

具体解释如下:

i:0:代表数组中的第一个元素,其索引为0。

s:3:"pig"; 代表第一个元素的取值为"pig",即猪。

i:1:代表数组中的第二个元素,其索引为1。

s:5:"tiger"; 代表第二个元素的取值为"tiger",即老虎。

i:2:代表数组中的第三个元素,其索引为2。

s:8:"elephant"; 代表第三个元素的取值为"elephant",即大象。

综上所述,这个输入以一种结构化的方式表示了一个包含三个元素的数组,其中每个元素都有一个索引和对应的取值。

第二段输出中每一个字符分别代表:

Array:表示这是一个数组。

[0] => pig:表示数组中的第一个元素的索引为0,对应的取值为"pig",即猪。

[1] => tiger:表示数组中的第二个元素的索引为1,对应的取值为"tiger",即老虎。

[2] => elephant:表示数组中的第三个元素的索引为2,对应的取值为"elephant",即大象。

这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。常见的php系列化和反系列化方式主要有:serialize,unserialize;json_encode,json_decode。

在PHP中对不同类型的数据用不同的字母来标识:

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 表示的是四种标量类型,目前其它语言所实现的 PHP 序列化程序基本上都实现了对这些类型的序列化和反序列化,不过有一些实现中对 s (字符串)的实现存在问题。

a、O 属于最常用的复合类型,大部分其他语言的实现都很好的实现了对 a 的序列化和反序列化,但对 O 只实现了 PHP4 中对象序列化格式,而没有提供对 PHP 5 中扩展的对象序列化格式的支持。

r、R 分别表示对象引用和指针引用,这两个也比较有用,在序列化比较复杂的数组和对象时就会产生带有这两个标示的数据。

C 是 PHP5 中引入的,它表示自定义的对象序列化方式。

U 是 PHP6 中才引入的,它表示 Unicode 编码的字符串。因为 PHP6 中提供了 Unicode 方式保存字符串的能力,因此它提供了这种序列化字符串的格式,不过这个类型 PHP5、PHP4 都不支持,而这两个版本目前是主流,因此在其它语言实现该类型时,不推荐用它来进行序列化,不过可以实现它的反序列化过程。

o标示在 PHP3 中被引入用来序列化对象,到了 PHP4 以后就被 O 取代了。在 PHP3 的源代码中可以看到对 o 的序列化和反序列化与数组 a 基本上是一样的。但是在 PHP4、PHP5 和 PHP6 的源代码中序列化部分里都找不到它。

我们知道属性访问权限有三个:private、protected、public,测试这三个属性的情况:

(1)public,该属性序列化后的结果正常,在预期之内;

(2)private,私有权限,也就是说该属性只能由类使用,为了区别,在序列化后,private属性会在自己的名字前面加上自己所属的类名,也即变成了demotest2,但是其长度为啥是11呢?写到文件使用HEXDUMP查看便知。

根据结果表明:私有属性在序列后类名前后均有%00,也即%00类名%00属性名

(3)protected,该属性和private有些类似,但是长度怎么计算呢?看上图便知!protected在序列化时序列化后的结果是%00*%00属性名

<?php
class demo
{
    public $test = 'hacker';
    private $test2 = 'pentester';
    protected $test3 = 'redhat';
}
$object = new demo();
$uns = serialize($object);
echo $uns;
?>

总的来说就是:

public:长度正常不变,为原本名称

private:在原本名称的基础上,前面加一个类名,在类名的前后各加一个空格

protected:在原本名称的基础上,前面加一个*号,在*号前后各加一个空格

下方测试结果和上方测试结果一样,说明定义的方法不影响序列化的结果,总之:序列化只序列化属性,不序列化方法

<?php
class demo
{
    public $test = 'hacker';
    private $test2 = 'pentester';
    protected $test3 = 'redhat';

    public function test4($test)
    {
        $this->test4 = $test;
    }
    public function test5($test)
    {
        return $this->test;
    }

}
$object = new demo();
$uns = serialize($object);
echo $uns;
?>

注意:

在反序列化的过程中必须保证当前作用域下类是存在的,否则无法完成反序列化操作。

反序列化之后的对象在文件执行结束后就会被销毁

小结:

PHP 中的 serialize() 函数用于将复杂的数据结构(如对象、数组、数值、字符串等)转换成一个可存储或传输的字符串形式。当序列化包含类实例的对象时,serialize() 对类变量的处理方式会根据这些变量的访问修饰符(public、protected、private)有所不同。

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值