php序列化&反序列化坑
一:
在php中如果我们统一编码是没有什么问题了,但是很多朋友会发现一个问题就是utf8和gbk编码中返回的值会有所区别:
php 在utf8和gbk编码下使用serialize和unserialize互相序列化和反序列化会出现无法成功反序列化的问题。
问题出现的原因主要是在不同编码下strlen函数计算中文字符串长度不同的原因。
<?php
$array=array('title'=>'php教程分享网','url'=>'http://www.111cn.net');
echo serialize($array);
//gbk编码 a:2:{s:5:"title";s:13:"php教程分享网";s:3:"url";s:20:"http://www.111cn.net";}
//utf8编码 a:2:{s:5:"title";s:18:"php教程分享网";s:3:"url";s:20:"http://www.111cn.net";}
?>
要解决这个问题就要在反序列化的时候重新修正字符串的长度。
解决方案
<?php
$str='a:2:{s:5:"title";s:13:"php教程分享网";s:3:"url";s:20:"http://www.111cn.net";}';
$regex = '/s\:(\d+)\:\"([^\"]+)\"/isx'; $str = preg_replace_callback(
$regex ,
"fixser",
$str); function fixser($matches)
{
return 's:'.strlen($matches[2]).':'.'"'.$matches[2].'"';
}
?>
可以改成匿名函数
<?php
$str='a:2:{s:5:"title";s:13:"php教程分享网";s:3:"url";s:20:"http://www.111cn.net";}';
$regex = '/s\:(\d+)\:\"([^\"]+)\"/isx'; $str = preg_replace_callback(
$regex ,
function ($matches)
{
return 's:'.strlen($matches[2]).':'.'"'.$matches[2].'"';
},
$str);
?>
PHP序列化格式后的内容是简单的文本格式,但是对字母大小写和空白(空格、回车、换行等)敏感,而且字符串是按照字节(或者说是 8 位的字符)计算的,因此,更合适的说法是 PHP 序列化后的内容是字节流格式。
因此用其他语言实现时,如果所实现的语言中的字符串不是字节储存格式,而是 Unicode 储存格式的话,序列化后的内容不适合保存为字符串,而应保存为字节流对象或者字节数组,否则在与 PHP 进行数据交换时会产生错误。
PHP 对不同类型的数据用不同的字母进行标示,Yahoo 开发网站提供的 Using Serialized PHP with Yahoo! Web Services 一文中给出所有的字母标示及其含义:
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
方式保存字符串的能力,因此它提供了这种PHP序列化格式字符串的格式,不过这个类型 PHP5、PHP4
都不支持,而这两个版本目前是主流,因此在其它语言实现该类型时,不推荐用它来进行序列化,不过可以实现它的反序列化过程。在后面我也会对它的格式进行说
明。
最后还有一个 o,这也是我唯一还没弄清楚的一个数据类型标示。这个标示在 PHP3 中被引入用来序列化对象,但是到了 PHP4 以后就被 O
取代了。在 PHP3 的源代码中可以看到对 o 的序列化和反序列化与数组 a 基本上是一样的。但是在 PHP4、PHP5 和 PHP6
的源代码中PHP序列化格式部分里都找不到它的影子,但是在这几个版本的反序列化程序源代码中却都有对它的处理,不过把它处理成什么我还没弄清楚。因此对
它暂时不再作更多说明了。
//序列化一个数组:
serialize(array("asdoasod\'asdasd", "asdaspdaso\\\\\\pdopasopd"));
//返回结果:
a:2:{i:0;s:16:"asdoasod\'asdasd";i:1;s:22:"asdaspdaso\\\pdopasopd";} //我们一般存进数据库,带\号直接存进数据库会有一个问题,会出现自动去除'\'
//假如去除了'\'
//s:16: 这个16代表长度
//再从数据库中取出来数据,s:16的长度将会变短,这个时候: unserialize(); //就会出现问题!
php序列化&反序列化坑的更多相关文章
- php json与xml序列化/反序列化
在web开发中对象的序列化与反序列化经常使用,比较主流的有json格式与xml格式的序列化与反序列化,今天想写个jsop的小demo,结果发现不会使用php序列化,查了一下资料,做个笔记 简单数组js ...
- 序列化反序列化api(入门级)
定义: java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 为什么字符串通常也会进行序列化? 对象需要进行序列化的原因:保证对象的状态不变 ...
- python_way ,day5 模块,模块3 ,双层装饰器,字符串格式化,生成器,递归,模块倒入,第三方模块倒入,序列化反序列化,日志处理
python_way.day5 1.模块3 time,datetime, json,pickle 2.双层装饰器 3.字符串格式化 4.生成器 5.递归 6.模块倒入 7.第三方模块倒入 8.序列化反 ...
- C#之你懂得的序列化/反序列化
前言:写此文章一方面是为了巩固对序列化的认识,另一方面是因为本人最近在面试,面试中被问到“为什么要序列化”.虽然一直在使用,自己也反复的提到序列化,可至于说为什么要序列化,还真的没想过,所以本文就这样 ...
- springboot学习(三)——http序列化/反序列化之HttpMessageConverter
以下内容,如有问题,烦请指出,谢谢! 上一篇说掉了点内容,这里补上,那就是springmvc的http的序列化/反序列化,这里简单说下如何在springboot中使用这个功能. 使用过原生netty ...
- java序列化反序列化深入探究
When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想 ...
- java序列化反序列化深入探究(转)
When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想 ...
- C# XML序列化/反序列化参考
.NET提供了很不错的XML序列化/反序列化器,(它们所在的命名空间为System.Xml.Serialization)这是很方便的,下面对它的使用做一些总结,以供参考. 1,简单序列化 public ...
- 二进制数据的序列化反序列化和Json的序列化反序列化的重要区别
前言:最近一个一个很奇怪的问题,很明白的说,就是没看懂,参照下面的代码: /// <summary> /// 反序列化对象 /// </summary> /// <typ ...
随机推荐
- 解决Windows下网络原因Composer安装失败问题的方法
由于Composer镜像都在国外,所以直接在官网下载Windows Installer后安装很多情况下是无法成功安装的. 解决办法: 1,将php添加到系统环境变量,并开启openssl扩展. 2,点 ...
- C# Socket的粘包处理(转)
http://www.cnblogs.com/aarond/p/Socket111.html 当socket接收到数据后,会根据buffer的大小一点一点的接收数据,比如: 对方发来了1M的数据量过来 ...
- iOS手势UIGestureRecognizer的使用失效问题
问题:视图正常展示在界面中,父层是放在window上的,底部的一个控件的点击事件失效(所有设置都正常) 解决思路:虽然视图能够正常展示,但是发现父类视图的底部尺寸比子类的视图的尺寸小,也就是说上层视图 ...
- 阿里最新出的图书《码出高效:Java开发手册》宣传手册图片里出了比较搞笑的错误,大家没有发现?
- Java IO 学习(五)跟踪三个文件IO方法的调用链
假设我们想要用Java读取一个二进制文件,有好几种方式,本文会选取其中比较典型的三种方式进行详细分析 0. 准备工作 安装openjdk-1.8.0.141(普通的jdk中涉及IO的很多代码是闭源的, ...
- 快速幂取模(当数很大时,相乘long long也会超出的解决办法)
当几个数连续乘最后取模时,可以将每个数字先取模,最后再取模,即%对于*具有结合律.但是如果当用来取模的数本身就很大,采取上述方法就不行了.这个时候可以借鉴快速幂取模的方法,来达到大数相乘取模的效果. ...
- UVA 437 巴比伦塔 【DAG上DP/LIS变形】
[链接]:https://cn.vjudge.net/problem/UVA-437 [题意]:给你n个立方体,让你以长宽为底,一个个搭起来(下面的立方体的长和宽必须大于上面的长和宽)求能得到的最长高 ...
- Ngnix 安装常见错误的处理
错误: 解决方案:(联网下) 出现上面的问题是由于没有c++编译器造成 # yum -y install gcc-c++ 使用上面的命令即可安装c++解决问题 如果确实c编译器,使用如下命令解 ...
- FZU-2267 The Bigger the Better(字符串,模拟)
Problem 2267 The Bigger the Better Accept: 132 Submit: 935Time Limit: 1500 mSec Memory Limit ...
- luogu P1069 细胞分裂
题目描述 Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家.现在,他正在为一个细胞实 验做准备工作:培养细胞样本. Hanks 博士手里现在有 N 种细胞,编号从 1~N,一个 ...