文档章节

PHP: pack/unpack补遗

陈亦
 陈亦
发布于 2014/02/23 09:31
字数 668
阅读 3758
收藏 35

pack/unpack的介绍和使用加上这篇就第三篇了。确实知识点比较多,这篇算是收尾之作吧。仔细去文档上看pack/unpack的格式化字符说明,就会发现s, S, i, I, l, L, f, d都没有对应的大端序和小端序的格式化字符,所以有需要的时候必须自己实现。这个真不知道PHP开发项目组是怎么想的!

而且确实有人在stackoverflow上这么问了,详见:php-pack-format-for-signed-32-int-big-endian 。stackoverflow上的答案比较巧妙,所以我在这里进行借鉴。

L表示无符号长整型,按主机字节序。N表示无符号长整型,大端序。它们都是32位的,所以如果用L和N对同一个整数进行打包,如果结果相等,则本机字节序就是大端序,否则就是小端序。代码如下:

<?php
define('BIG_ENDIAN', pack('L', 1) === pack('N', 1));

if (BIG_ENDIAN)
{
	echo "大端序";
}
else
{
	echo "小端序";
}

echo "\n";

$ php -f test.php
小端序

大端序和小端序事实上是相反的字节序,比如要实现无符号短整型的大端序和小端序,可以用s格式化字符先进行打包,再判断大小端来决定是否需要反转字符串,代码如下:

<?php
define('BIG_ENDIAN', pack('L', 1) === pack('N', 1));

// 有符号16位整型大端序
function pack_int16s_be($num)
{
	if (BIG_ENDIAN)
	{
		return pack("s", $num);
	}

	return strrev(pack("s", $num));
}

// 有符号16位整型小端序
function pack_int16_le($num)
{
	if (BIG_ENDIAN)
	{
		return strrev(pack("s", $num));
	}

	return pack("s", $num);
}

其它几个也是类似如此实现。但是需要注意的是还需要实现相应版本的unpack,可参考我之前的一篇文章:PHP: chr和pack、unpack那些事

对于实现这几个函数倒不是难事,但在实际打包解包的时候就比较麻烦了。pack还比较好,只是分开打包,再作字符串连接。但是对unpack来说,需要根据协议长度,将字节流拆分然后分别解包,确实有点坑。

本篇文章基本上也就这些知识点,pack/unpack就告一段落了,欢迎大家一起交流~

© 著作权归作者所有

共有 人打赏支持
陈亦
粉丝 236
博文 23
码字总数 53194
作品 0
浦东
高级程序员
加载中

评论(11)

虎爷
虎爷
你这算什么,我在 Windows x64 环境下, unpack N 格式能得到负值。。。
军区文工团
军区文工团

引用来自“军区文工团”的评论

問博主一個問題,pack打包后,然後echo這個語句是不是對應有一個相當於解包的操作

引用来自“陈一回”的评论

http://my.oschina.net/goal/blog/202378
再次感激
陈亦
陈亦

引用来自“军区文工团”的评论

問博主一個問題,pack打包后,然後echo這個語句是不是對應有一個相當於解包的操作
http://my.oschina.net/goal/blog/202378
军区文工团
军区文工团
問博主一個問題,pack打包后,然後echo這個語句是不是對應有一個相當於解包的操作
军区文工团
军区文工团
感激!
陈亦
陈亦

引用来自“solu”的评论

引用来自“陈一回”的评论

引用来自“solu”的评论

记得Python的 Struck.pack 也一大堆format的参数,还以为有什么标准,然后PHP和Python都按这标准做。谁知道对比一下发现PHP和Python的根本对不上。

格式化字符不一样也没有什么关系的吧,像python的struct.pack还提供@, !, >之类的用来指示字节序。

嗯,只是觉得不便于记忆,只好用的时候翻翻手册。

这个本来就没标准,反正按字节序打包就是了。各家实现各家的。不过看来php的pack和perl的pack最像。13
solu
solu

引用来自“陈一回”的评论

引用来自“solu”的评论

记得Python的 Struck.pack 也一大堆format的参数,还以为有什么标准,然后PHP和Python都按这标准做。谁知道对比一下发现PHP和Python的根本对不上。

格式化字符不一样也没有什么关系的吧,像python的struct.pack还提供@, !, >之类的用来指示字节序。

嗯,只是觉得不便于记忆,只好用的时候翻翻手册。
陈亦
陈亦

引用来自“solu”的评论

记得Python的 Struck.pack 也一大堆format的参数,还以为有什么标准,然后PHP和Python都按这标准做。谁知道对比一下发现PHP和Python的根本对不上。

格式化字符不一样也没有什么关系的吧,像python的struct.pack还提供@, !, >之类的用来指示字节序。
solu
solu
记得Python的 Struck.pack 也一大堆format的参数,还以为有什么标准,然后PHP和Python都按这标准做。谁知道对比一下发现PHP和Python的根本对不上。
陈亦
陈亦

引用来自“我是菜菜”的评论

茅塞顿开!这几天让java 的字节数组整的头大说是什么倒序 现在明白了

呵呵,有帮助到你就好。给你再补充点:字节序是以字节为单位的,只是在CPU存储时才会有大小端之分,除非是直接拷贝内存或做类型转换截断,否则对我们程序中的变量是没什么影响的。因为字节序是以字节为单位,所以单字节类型比如char没有大小端序之分(单字节,你懂的),而对于字符串,因为它本质上是字节流,比如一个ASCII字符是单字节,而多字节字符本质上是由多个单字节组成的(java的内码是Unicode,所以在java中一个汉字是2个字节),因此也是没有大小端序之分的。0
php pack 和 unpack 函数

输出: PHP php 用unpack 函数后得到的就是那3个数作为键值的数组,那怎么把这个数组当作pack函数的三个参数传进去 我用了eval 函数,但是结果是false,厉害的帮忙解决下,不胜感激,像这种参...

李佳顺
2014/01/08
305
4
PHP: chr和pack、unpack那些事

PHP是一门很灵活的语言。正因为它太灵活了,甚至有些怪异,所以大家对它的评价褒贬不一。其实我想说的是,任何一门语言都有它自身的哲学,有它存在的出发点。PHP为Web而生,它以快速上手、快...

陈亦
2014/02/23
0
31
Linux安装jdk出现java/lang/NoClassDefFoundError

java -version Error occurred during initialization of VM java/lang/NoClassDefFoundError: java/lang/Object 检查lib目录下的tools是否是tools.pack格式(即lib/tools.pack)和 jre/lib目......

squanchao
2016/12/09
5
0
用socket方式与服务器通信,php如何处理网络字节顺序

最近搞一个用socket与服务端通信的东西,之前完全没接触过,大概意思我说一下,希望有人能帮帮忙。 数据传输格式:报文头+报文体 服务端要求报文头中int类型字段用网络字节顺序,我大概查了下...

dongyao
2013/12/01
1K
5
msgpack 真的比 protobuf buffers 快 4 倍吗?

hprose serialize Runtime:0.2334s json encode Runtime:15.2883s serialize Runtime:0.7090s msgpack_pack Runtime:0.6883s hprose unserialize Runtime:0.5439s json decode Runtime:24.29......

andot
2015/04/18
3.4K
4

没有更多内容

加载失败,请刷新页面

加载更多

Shiro | 实现权限验证完整版

写在前面的话 提及权限,就会想到安全,是一个十分棘手的话题。这里只是作为学校Shiro的一个记录,而不是,权限就应该这样设计之类的。 Shiro框架 1、Shiro是基于Apache开源的强大灵活的开源...

冯文议
今天
1
0
linux 系统的运行级别

运行级别 运行级别 | 含义 0 关机 1 单用户模式,可以想象为windows 的安全模式,主要用于修复系统 2 不完全的命令模式,不含NFS服务 3 完全的命令行模式,就是标准的字符界面 4 系统保留 5 ...

Linux学习笔记
今天
2
0
学习设计模式——命令模式

任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。 解决了这...

江左煤郎
今天
3
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
15
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部