浅谈PHP中pack、unpack的详细用法


Posted in PHP onMarch 12, 2018

PHP中有两个函数pack和unpack,很多PHPer在实际项目中从来没有使用过,甚至也不知道这两个方法是用来干嘛的。这篇文章来为大家介绍一下它俩到底是用来干啥的。

pack

string pack ( string $format [, mixed $args [, mixed $... ]] )

该函数用来将对应的参数($args)打包成二进制字符串。

其中第一个参数$format,有如下选项(可选参数很多,后面会选几个常用的讲解):

Code Description
a 以NUL字节填充字符串空白
A 以SPACE(空格)填充字符串
h 十六进制字符串,低位在前
H 十六进制字符串,高位在前
c 有符号字符
C 无符号字符
s 有符号短整型(16位,主机字节序)
S 无符号短整型(16位,主机字节序)
n 无符号短整型(16位,大端字节序)
v 无符号短整型(16位,小端字节序)
i 有符号整型(机器相关大小字节序)
I 无符号整型(机器相关大小字节序)
l 有符号长整型(32位,主机字节序)
L 无符号长整型(32位,主机字节序)
N 无符号长整型(32位,大端字节序)
V 无符号长整型(32位,小端字节序)
q 有符号长长整型(64位,主机字节序)
Q 无符号长长整型(64位,主机字节序)
J 无符号长长整型(64位,大端字节序)
P 无符号长长整型(64位,小端字节序)
f 单精度浮点型(机器相关大小)
d 双精度浮点型(机器相关大小)
x NUL字节
X 回退一字节
Z 以NUL字节填充字符串空白(new in PHP 5.5)
@ NUL填充到绝对位置

这么多参数看下来,我第一次是真心懵逼了,大部分说明都很好理解,但是其中的主机、大端、小端等字节序是什么鬼呢?接下里的内容比较枯燥,但必须理解才行,坚持吧。

字节序是什么?

就是字节的顺序,说白了就是多字节数据的存放顺序(一个字节显然不需要顺序)。

比如A和B分别对应的二进制表示为0100 0001、0100 0010。对于储存字符串AB,我们可以0100 0001 0100 0010也可以0100 0010 0100 0001,这个顺序就是所谓的字节序。

高/低位字节

比如字符串AB,左高右低(我们正常的阅读顺序),A为高字节,B为低字节

高/低地址

假设0x123456是按从高位到底位的顺序储存,内存中是这样存放的:

高地址 -> 低地址
12 -> 34 -> 56

大端字节序(网络字节序)

大端就是将高位字节放到内存的低地址端,低位字节放到高地址端。网络传输中(比如TCP/IP)低地址端(高位字节)放在流的开始,对于2个字节的字符串(AB),传输顺序为:A(0-7bit)、B(8-15bit)。

那么小端字节序自然和大端相反。

主机字节序

表示当年机器的字节序(也就是网络字节序是确定的,而主机字节序是依机器确定的),一般为小端字节序。

a和A(打包字符串,用NUL或者空格填充)

$string = pack('a6', 'china');
var_dump($string); //输出结果: string(6) "china",最后一个字节是不可见的NUL
echo ord($string[5]); //输出结果: 0(ASCII码中0对应的就是nul)

//A同理
$string = pack('A6', 'china');
var_dump($string); //输出结果: string(6) "china ",最后一个字节是空格
echo ord($string[5]); //输出结果: 32(ASCII码中32对应的就是空格)

浅谈PHP中pack、unpack的详细用法

附赠ASCII表一张(linux/unix下可以使用man ascii查看)

h和H

$string = pack('H3', 281);
var_dump($string); //输出结果: string(2) "("

for($i=0;$i<strlen($string);$i++) {
echo ord($string[$i]) . PHP_EOL;
}
//输出结果: 40 16

h和H需要特殊说明一下,它们是将对应的参数看做十六进制字符然后打包。什么意思呢?比如上面的281,打包前会将281转换为0x281,因为十六进制的一位对应二进制的四位,上面的0x281只有1.5个字节,后面会默认补0变成0x2810,0x28对应的十进制为40((),0x10对应的十进制为16(dle不可见字符),懂了吧?不懂可以给我留言。。

c和C

$string = pack('c3', 67, 68, -1);
var_dump($string); //输出:string(3) "CD�"

for($i=0;$i<strlen($string);$i++) {
echo ord($string[$i]) . PHP_EOL;
}
//输出: 67 68 225

最后输出本能应该觉得是67 68 -1

ord获取的是字符的ASCII码(范围0-255),这时-1(0000 0001)对应的字符将以补码的形式输出也就是255(1111 1110 + 0000 0001 = 1111 1111)

整型相关

所有的整型类型使用方法完全一样,主要注意它们的位和字节序就可以了,下面以L作为例子展示

$string = pack('L', 123456789);
var_dump($string); //输出:string(4) "�["

for($i=0;$i<strlen($string);$i++) {
echo ord($string[$i]) . PHP_EOL;
}
//输出: 21 205 91 7

f和d

$string = pack('f', 12345.123);
var_dump($string);
//输出:string(4) "~�@F"
var_dump(unpack('f', $string)); //这里提前用到了unpack,后面会讲解
//输出:float(12345.123046875)

f和d是针对浮点数打包,至于为什么打包前是12345.123解包后是12345.123046875,这个和浮点数的储存有关系,后面可以单开一个文章讲解一下IEEE标准

x、X、Z、@

$string = pack('x'); //打包一个nul字符串
echo ord($string); //输出: 0

关于X(大写X),试了N次,没搞明白怎么用,有清楚的童鞋可以给我留言,多谢。

$string = pack('Z2', 'abc5'); //其实就是将从Z后面的数字位置开始,全部设置为nul
var_dump($string); //输出:string(2) "a"

for($i=0;$i<strlen($string);$i++) {
echo ord($string[$i]) . PHP_EOL;
}
//输出: 97 0
$string = pack('@4'); //我理解为填充N个nul
var_dump($string); //输出: string(4) ""

for($i=0;$i<strlen($string);$i++) {
echo ord($string[$i]) . PHP_EOL;
}
//输出: 0 0 0 0

unpack

array unpack ( string $format , string $data )

unpack的使用相当简单,就是讲pack打包的数据解包,打包的时候用的什么参数,就用什么参数解包,具体使用懒得说了,列几个小例子

$string = pack('L4', 1, 2, 3, 4);
var_dump(unpack('L4', $string));
//输出:
array(4) {
[1]=>
int(1)
[2]=>
int(2)
[3]=>
int(3)
[4]=>
int(4)
}

$string = pack('L4', 1, 2, 3, 4);
var_dump(unpack('Ll1/Ll2/Ll3/Ll4', $string)); //可以指定key,用/分割
//输出:
array(4) {
["l1"]=>
int(1)
["l2"]=>
int(2)
["l3"]=>
int(3)
["l4"]=>
int(4)
}

这两个函数到底有啥用途

  1. 数据通信(通过二进制格式与其它语言通信)
  2. 数据加密(如果不告诉第三方你的打包方式,对方解包的难度就相对很大)
  3. 节省空间(比如比较大的数字按字符串储存会浪费很多空间,打包成二进制格式才需要4位<32位数字>)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP4引用文件语句的对比
Oct 09 PHP
php 远程图片保存到本地的函数类
Dec 08 PHP
phpmyadmin MySQL 加密配置方法
Jul 05 PHP
PHP时间戳 strtotime()使用方法和技巧
Oct 29 PHP
php实现随机显示图片方法汇总
May 21 PHP
php获取指定范围内最接近数的方法
Jun 02 PHP
PHP封装CURL扩展类实例
Jul 28 PHP
php进行ip地址掩码运算处理的方法
Jul 11 PHP
yii的入口文件index.php中为什么会有这两句
Aug 04 PHP
php抽象方法和抽象类实例分析
Dec 07 PHP
php使用Jpgraph创建折线图效果示例
Feb 15 PHP
laravel + vue实现的数据统计绘图(今天、7天、30天数据)
Jul 31 PHP
阿里云Win2016安装Apache和PHP环境图文教程
Mar 11 #PHP
Yii2 中实现单点登录的方法
Mar 09 #PHP
php中输出json对象的值(实现方法)
Mar 07 #PHP
php 读写json文件及修改json的方法
Mar 07 #PHP
php读取本地json文件的实例
Mar 07 #PHP
PHP中in_array的隐式转换的解决方法
Mar 06 #PHP
php连接MSsql server的五种方法总结
Mar 04 #PHP
You might like
利用switch语句进行多选一判断的实例代码
2016/11/14 PHP
PHP7引入的&quot;??&quot;和&quot;?:&quot;的区别讲解
2019/04/08 PHP
让div层随鼠标移动的实现代码 ie ff
2009/12/18 Javascript
JavaScript 对象的属性和方法4种不同的类型
2010/03/19 Javascript
13 个JavaScript 性能提升技巧分享
2012/07/26 Javascript
解析John Resig Simple JavaScript Inheritance代码
2012/12/03 Javascript
解决jquery中美元符号命名冲突问题
2014/01/08 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
2014/04/06 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
jquery实现的下拉和收缩效果示例
2014/08/21 Javascript
javascript数据结构与算法之检索算法
2015/04/04 Javascript
理解JS事件循环
2016/01/07 Javascript
倾力总结40条常见的移动端Web页面问题解决方案
2016/05/24 Javascript
Angular 2应用的8个主要构造块有哪些
2016/10/17 Javascript
浅谈vue+webpack项目调试方法步骤
2017/09/11 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
详解关于element el-button使用$attrs的一个注意要点
2018/11/09 Javascript
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
2019/01/20 Javascript
JS eval代码快速解密实例解析
2020/04/23 Javascript
[01:50]《我与DAC》之玩家:iG夺冠时的那面红旗
2018/03/29 DOTA
Python中每次处理一个字符的5种方法
2015/05/21 Python
Python 在字符串中加入变量的实例讲解
2018/05/02 Python
Python运维之获取系统CPU信息的实现方法
2018/06/11 Python
python 三元运算符使用解析
2019/09/16 Python
Python爬取新型冠状病毒“谣言”新闻进行数据分析
2020/02/16 Python
解决ROC曲线画出来只有一个点的问题
2020/02/28 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
2020/06/22 Python
python正则表达式re.match()匹配多个字符方法的实现
2021/01/27 Python
Reebok俄罗斯官方网上商店:购买锐步运动服装和鞋子
2016/09/26 全球购物
波兰最大的度假胜地和城市公寓租赁运营商:Sun & Snow
2018/10/18 全球购物
工程班组长岗位职责
2013/12/30 职场文书
小学英语教学反思案例
2014/02/04 职场文书
质量负责人岗位职责
2015/02/15 职场文书
React配置子路由的实现
2021/06/03 Javascript
javascript的var与let,const之间的区别详解
2022/02/18 Javascript