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);
}
最新文章
- MySQL 显示命令
- easyui DataGrid 工具类之 util js
- 安装Vmware workstation虚拟机(含软件和注册码)
- 1008. Elevator (20)
- VS2012的变态优化,双循环变单循环
- selenium之多线程启动grid分布式测试框架封装(四)
- 网购的一套UI代码的始末
- ETL总结(扫盲版)
- Android 开发 8.0版本启动Service的方法
- bzoj 1264: [AHOI2006]基因匹配Match (树状数组优化dp)
- http认证中的nonce与timestamp解释
- BZOJ2568 比特集合(树状数组)
- [Algorithm] Print 2-D array in spiral order
- bzoj 3853 : GCD Array
- 【Android】3.2 基本地图功能
- less基本知识总结
- eclipse svn 冲突解决
- win下安装wget以及使用wget
- 使用ConfigFilter
- #include stdio.h(B)