首页 后端开发 php教程 pack、unpack的使用详解

pack、unpack的使用详解

Mar 24, 2018 pm 04:59 PM
详解

这次给大家带来pack、unpack的使用详解,使用pack、unpack的注意事项有哪些,下面就是实战案例,一起来看一下。

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 单精度浮点型
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填充到绝对位置
(机器相关大小)
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对应的就是空格)
登录后复制

附赠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(&#39;c3&#39;, 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(&#39;L&#39;, 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(&#39;f&#39;, 12345.123);
var_dump($string);
//输出:string(4) "~�@F"
var_dump(unpack(&#39;f&#39;, $string)); //这里提前用到了unpack,后面会讲解
//输出:float(12345.123046875)
登录后复制

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

x、X、Z、@

$string = pack(&#39;x&#39;); //打包一个nul字符串
echo ord($string); //输出: 0
登录后复制

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

$string = pack(&#39;Z2&#39;, &#39;abc5&#39;); //其实就是将从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(&#39;@4&#39;); //我理解为填充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(&#39;L4&#39;, 1, 2, 3, 4);
var_dump(unpack(&#39;L4&#39;, $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中文网其它相关文章!

推荐阅读:

PHP怎样生成随机数

Post无法获取表单数据

以上是pack、unpack的使用详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

C++中的众数函数详解 C++中的众数函数详解 Nov 18, 2023 pm 03:08 PM

C++中的众数函数详解在统计学中,众数指的是一组数据中出现次数最多的数值。在C++语言中,我们可以通过编写一个众数函数来找到任意一组数据中的众数。众数函数的实现可以采用多种不同的方法,下面将详细介绍其中两种常用的方法。第一种方法是使用哈希表来统计每个数字出现的次数。首先,我们需要定义一个哈希表,将每个数字作为键,出现次数作为值。然后,对于给定的数据集,我们遍

Win11管理员权限获取详解 Win11管理员权限获取详解 Mar 08, 2024 pm 03:06 PM

Windows操作系统是全球最流行的操作系统之一,其新版本Win11备受瞩目。在Win11系统中,管理员权限的获取是一个重要的操作,管理员权限可以让用户对系统进行更多的操作和设置。本文将详细介绍在Win11系统中如何获取管理员权限,以及如何有效地管理权限。在Win11系统中,管理员权限分为本地管理员和域管理员两种。本地管理员是指具有对本地计算机的完全管理权限

Oracle SQL中的除法运算详解 Oracle SQL中的除法运算详解 Mar 10, 2024 am 09:51 AM

OracleSQL中的除法运算详解在OracleSQL中,除法运算是一种常见且重要的数学运算操作,用于计算两个数相除的结果。除法在数据库查询中经常用到,因此了解OracleSQL中的除法运算及其用法是数据库开发人员必备的技能之一。本文将详细讨论OracleSQL中除法运算的相关知识,并提供具体的代码示例供读者参考。一、OracleSQL中的除法运算

C++中的取余函数详解 C++中的取余函数详解 Nov 18, 2023 pm 02:41 PM

C++中的取余函数详解在C++中,取余运算符(%)用于计算两个数相除的余数。它是一种二元运算符,其操作数可以是任何整数类型(包括char、short、int、long等),也可以是浮点数类型(如float、double)。取余运算符返回的结果与被除数的符号相同。例如,对于整数的取余运算,我们可以使用以下代码来实现:inta=10;intb=3;

Vue.nextTick函数用法详解及在异步更新中的应用 Vue.nextTick函数用法详解及在异步更新中的应用 Jul 26, 2023 am 08:57 AM

Vue.nextTick函数用法详解及在异步更新中的应用在Vue开发中,经常会遇到需要进行异步更新数据的情况,比如在修改DOM后需要立即更新数据或者在数据更新后需要立即进行相关操作。而Vue提供的.nextTick函数就是为了解决这类问题而出现的。本文就会详细介绍Vue.nextTick函数的用法,并结合代码示例来说明它在异步更新中的应用。一、Vue.nex

php-fpm调优方法详解 php-fpm调优方法详解 Jul 08, 2023 pm 04:31 PM

PHP-FPM是一种常用的PHP进程管理器,用于提供更好的PHP性能和稳定性。然而,在高负载环境下,PHP-FPM的默认配置可能无法满足需求,因此我们需要对其进行调优。本文将详细介绍PHP-FPM的调优方法,并给出一些代码示例。一、增加进程数默认情况下,PHP-FPM只启动少量的进程来处理请求。在高负载环境下,我们可以通过增加进程数来提高PHP-FPM的并发

PHP模运算符的作用及用法详解 PHP模运算符的作用及用法详解 Mar 19, 2024 pm 04:33 PM

PHP中的模运算符(%)是用来获取两个数值相除的余数的。在本文中,我们将详细讨论模运算符的作用及用法,并提供具体的代码示例来帮助读者更好地理解。1.模运算符的作用在数学中,当我们将一个整数除以另一个整数时,会得到一个商和一个余数。例如,当我们将10除以3时,商为3,余数为1。模运算符就是用来获取这个余数的。2.模运算符的用法在PHP中,使用%符号来表示模

linux系统调用system()函数详解 linux系统调用system()函数详解 Feb 22, 2024 pm 08:21 PM

Linux系统调用system()函数详解系统调用是Linux操作系统中非常重要的一部分,它提供了一种与系统内核进行交互的方式。其中,system()函数是一个常用的系统调用函数之一。本文将详细介绍system()函数的使用方法,并提供相应的代码示例。系统调用的基本概念系统调用是用户程序与操作系统内核交互的一种方式。用户程序通过调用系统调用函数来请求操作系统

See all articles