php函数unserialize数据返回false问题分析

unserialize的这个问题是由一个emlog论坛用户在使用时报错而发现的

问题表现情况如下:

emlog缓存的保存方式是将php的数据对象(数组)序列化(serialize)后以文件的形式存放,读取缓存的时候直接反序列化(unserialize)缓存字符串即可读取数据。

我从用户那里取到的缓存的序列化数据为:

a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬 间";s:3:"url";s:41:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}

咋一看了解序列化的人都会说,这个数据很正常啊,没什么问题呢。可是直接把这段字符串进行unserialize,返回的值却是个False;

代码

var_dump(unserialize(‘a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬间";s:3:"url";s:41:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}‘));

运行结果

问题出在哪里呢?答案是 s:41:"http://www.kaisay.cn/?plugin=kl_album"

序列化字符串中标定该字符串http://www.kaisay.cn/?plugin=kl_album的长度是41,可是我们自己数一下却只有37个字符。就是因为这个问题,导致php反序列化字符串失效。

如果将字符串长度改成37,那么程序就会顺利的反序列化

代码:

var_dump(unserialize(‘a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬 间";s:3:"url";s:37:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}‘));

通过google后才发现,这个问题国外已经很多的网友遇到了,在官方手册unserialize函数页面的评论中就有很多网友在讨论和研究这个问题的解决方案。

这种情况发生的原因有多种可能,最大的可能就是在序列化数据的时候的编码和反序列化时的编码不一样导致字符串的长度出现偏差。例如数据库编码latin1和UTF-8字符长度是不一样的。

总结:解决方案:

情况一:UTF-8

function mb_unserialize($serial_str) {
    $serial_str= preg_replace(‘!s:(\d+):"(.*?)";!se‘, "‘s:‘.strlen(‘$2‘).‘:\"$2\";‘", $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}

情况二:ASC

function asc_unserialize($serial_str) {
    $serial_str = preg_replace(‘!s:(\d+):"(.*?)";!se‘, ‘"s:".strlen("$2").":\"$2\";"‘, $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}
时间: 2024-10-12 08:20:13

php函数unserialize数据返回false问题分析的相关文章

php unserialize 返回false的解决方法

php 提供serialize(序列化) 与unserialize(反序列化)方法. 使用serialize序列化后,再使用unserialize反序列化就可以获取原来的数据.(改表结构或者进行下面操作) [php] view plaincopy <?php $arr = array( 'name' => 'fdipzone', 'gender' => 'male' ); $str = serialize($arr); //序列化 echo 'serialize str:'.$str.&

在$.post()函数外 使用$.post()返回函数的数据

本来我的想法是 将$.post()返回函数的数据取出来操作,在网上搜了很久,说是将$.post()方法改为同步,并将$.post()返回的数据赋值给一个全局变量的方法. function getData(pageCurrent){ var result; $.ajax({ url: "/ajax/signMain.ashx", async: true,//改为同步方式 type: "POST", data: { "pageCurrent": pa

php fopen函数返回false

使用yum安装的apache2.4.6   php 7.2.2  正确安装后使用fopen()函数打开文件时返回false 百度一下又三种原因 1.目录或者文件夹权限原因 (可以用   chmod -R 777 根目录      文件夹设置最高权限) 2.打开文件路径错误 3.打开方式错误(w,r,a)等 已确定不是上述错误 手动添加php错误报告 //error handler function function customError($errno, $errstr){ echo "<

Chromium硬件加速渲染的GPU数据上传机制分析

在Chromium中,WebGL端.Render端和Browser端通过命令缓冲区将GPU命令发送给GPU进程执行.GPU命令携带的简单参数也通过命令缓冲区发送给GPU进程,但是复杂参数,例如纹理数据,有可能太大以致命令缓冲区无法容纳,因此需要通过其它机制传递给GPU进程.本文接下来就主要以纹理数据上传为例,分析WebGL端.Render端和Browser端将GPU命令数据传递给GPU进程的机制. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! WebGL

结合centreon监控平台,对rrdtool的数据进行二次分析highchart展现

不知道,是不是所有的公司都会非常勤劳每个星期统计公司IDC的负载情况.如果有这方面需求,这个工作基本都是通过cacti或者centreon等等监控平台,手动选择特定时间特定服务的使用情况,如负载和内存等.最近有个需求,是要统计一天6个时间段的网络流量最大值和最小值,并登记入册.一般方法又是登陆监控平台,然后选择特定时间出图,然后再进行统计.这个方法,我真想说弱爆了,而我之前就一直重复着这样的工作.这次我打算利用自己不太娴熟的django.python.rrdtool.highcharts.jqu

将查询的结果封装成List&lt;Map&gt;与用回调函数实现数据的动态封装(44)

手工的开始QueryRunner类.实现数据封装: MapListHandler MapHandler BeanListHandler BeanHandler 第一步:基本的封装测试 写一个类,QueryRunner,实现一个方法query(sql)- List<map> package cn.itcast.dbutils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaD

mysql之数据处理函数与数据汇总函数

一.数据处理函数   1.函数 与其他大多数计算机语言一样, SQL支持利用函数来处理数据.函数一般是在数据上执行的,它给数据的转换和处理提供了方便. 注意:函数没有 SQL的可移植性强.能运行在多个系统上的代码称为可移植的( portable).相对来说,多数SQL语句是可移植的,在SQL实现之间有差异时,这些差异通常不那么难处理.而函数的可移植性却不强.几乎每种主要的 DBMS的实现都支持其他实现不支持的函数,而且有时差异还很大.为了代码的可移植,许多 SQL程序员不赞成使用特殊实现的功能.

使用PHP自带的filter函数进行数据校验

使用PHP自带的filter函数进行数据校验 PHP过滤器包含两种类型Validation:用来验证验证项是否合法Sanitization:用来格式化被验证的项目,因此它可能会修改验证项的值,将不合法的字符删除等. input_filters_list() 用来列出当前系统所支持的所有过滤器. <?php foreach(filter_list() as $id => $filter) {     echo $filter.' '.filter_id($filter)."\n&quo

函数和数据的继承及访问权限

C++通过类派生(Class Derivation)的机制支持继承(Inheritance).允许程序员在保持原有类特性的基础上进行扩展,增加功能,派生出新类. 继承的方式有以下2种:单一继承和多重继承. 派生类的定义中包括子类新增加的成员和继承父类需要重写的成员.C++允许在派生类中重新声明和定义这些成员函数,使这些函数具有新的功能,称之为重写或覆盖.重写函数起屏蔽.更新作用,取代基类成员,完成新功能. 测试一:子类继承基类的所有属性和函数,设基类函数和数据均为public类型,并且以publ