设为首页 收藏本站
查看: 592|回复: 0

[经验分享] PHP pack和unpack函数详解

[复制链接]

尚未签到

发表于 2017-4-2 11:02:01 | 显示全部楼层 |阅读模式
  pack
  压缩资料到位字符串之中。
  语法: string pack(string format, mixed [args]...);
  返回值: 字符串
  函数种类: 资料处理
内容说明  本函数用来将资料压缩打包到位的字符串之中。本函数和 Perl 的同名函数功能用法完全相同。
  参数 format 为压缩的格式,见下表
  a 将字符串空白以 NULL 字符填满
  A 将字符串空白以 SPACE 字符 (空格) 填满
  h 十六进位字符串,低位在前
  H 十六进位字符串,高位在前
  c 有号字符
  C 无号字符
  s 有号短整数 (十六位,依计算机的位顺序)
  S 无号短整数 (十六位,依计算机的位顺序)
  n 无号短整数 (十六位, 高位在后的顺序)
  v 无号短整数 (十六位, 低位在后的顺序)
  i 有号整数 (依计算机的顺序及范围)
  I 无号整数 (依计算机的顺序及范围)
  l 有号长整数 (卅二位,依计算机的位顺序)
  L 无号长整数 (卅二位,依计算机的位顺序)
  N 无号短整数 (卅二位, 高位在后的顺序)
  V 无号短整数 (卅二位, 低位在后的顺序)
  f 单精确浮点数 (依计算机的范围)
  d 倍精确浮点数 (依计算机的范围)
  x 空位
  X 倒回一位
  @ 填入 NULL 字符到绝对位置
  例子 1
  <?php
  echo pack("C3",80,72,80);
  ?>
  输出:
  PHP
  例子 2
  <?php
  echo pack("C*",80,72,80);
  ?>
  输出:
  PHP
  unpack
  解压缩位字符串资料。
  语法: string pack(string format, mixed [args]...);
  返回值: 数组
  函数种类: 资料处理
内容说明  本函数用来将位的字符串的资料解压缩。本函数和 Perl 的同名函数功能用法完全相同。参数 format 为压缩的格式,参见 pack 的格式表。
  例子 1
  <?php
  $data = "PHP";
  print_r(unpack("C*",$data));
  ?>
  输出:
  Array
  (
  [1] => 80
  [2] => 72
  [3] => 80
  )
  例子 2
  <?php
  $data = "PHP";
  print_r(unpack("C*myint",$data));
  ?>
  输出:
  Array
  (
  [myint1] => 80
  [myint2] => 72
  [myint3] => 80
  )
  例子 3
  <?php
  $bin = pack("c2n2",0x1234,0x5678,65,66);
  print_r(unpack("c2chars/n2int",$bin));
  ?>
  输出:
  Array
  (
  [chars1] => 52
  [chars2] => 120
  [int1] => 65
  [int2] => 66
  )
  玩了玩 PHP 的 pack/unpack !还是蛮简单的
  2007-07-04 16:34
  这几天要做双向的加解密,因为加密后的结果都是二进制的,不得不了解一下它了
  小try了一把pack/unpack,基本用法还是蛮简单的,下面的例子基本上是给了个做数据库的原型(嘻嘻,不能用PHP5了,只好用PHP4的语法写)
  <?php
  /**
  * 这是一个测试pack/unpack操作的东西
  * @author 张心灵
  * Email: zhangsilly@gmail.com
  *
  * 一下文件存储如下几个字段
  * 姓名: 长度 8 字节
  * 年龄: unsigned int
  * Email: 长度 30 字节
  */
  class Person_Data
  {
  /**
  * 数据库文件路径
  *
  * @var string
  */
  var $_database = './wps.db';
  /**
  * 打开一个数据库文件
  *
  * @param string $file 数据库文件名
  */
  function openDb($file = './wps.db')
  {
  $this->_database = $file;
  $this->_database = fopen($this->_database, 'ab+');
  }
  /**
  * 向数据库中写入一条记录
  *
  * @param array $data PHP4真的丑死了
  * @return void
  */
  function writeRecord($data)
  {
  $name = pack('a8', $data['name']);
  $age = pack('S', $data['age']);
  $email = pack('a30', $data['email']);
  fwrite($this->_database, $name . $age . $email);
  }
  /**
  * 读取一条记录
  *
  * @param int $count optional default to 0 记录id数
  * @return array
  */
  function read($count = 0)
  {
  rewind($this->_database);
  fseek($this->_database, 40 * $count);
  $return = array();
  $return['name'] = unpack('a8', fread($this->_database, 8));
  $return['name'] = $return['name'][1];
  $return['age'] = unpack('S', fread($this->_database, 2));
  $return['age'] = $return['age'][1];
  $return['email'] = unpack('a30', fread($this->_database, 30));
  $return['email'] = $return['email'][1];
  return $return;
  }
  }
  $me = array( 'name' => '张心灵',
  'age' => 23,
  'email' => 'zhangsilly@gmail.com');
  $data = new Person_Data();
  $data->openDb('./wps.db');
  //$data->writeRecord($me);
  print_r($data->read(1));
  以上文件运行了两侧,写入了两行记录,最后我读取第二行记录(索引自然从 1 开始)
  运行一切正常:
  Array
  (
  [name] => 张心灵
  [age] => 23
  [email] => zhangsilly@gmail.com
  )
  双就一个字!
  翻译:
  pack()函数的作用是:将数据压缩成一个二进制字符串。

  • a - NUL-padded string  a - NUL- 字符串填满[padded string]
  • A - SPACE-padded string  A - SPACE- 字符串填满[padded string]
  • h - Hex string, low nibble first  h – 十六进制字符串,低“四位元”[low nibble first]
  • H - Hex string, high nibble first  H - 十六进制字符串,高“四位元”[high nibble first]
  • c - signed char  c – 带有符号的字符
  • C - unsigned char  C – 不带有符号的字符
  • s - signed short (always 16 bit, machine byte order)  s – 带有符号的短模式[short](通常是16位,按机器字节顺序)
  • S - unsigned short (always 16 bit, machine byte order)  S – 不带有符号的短模式[short](通常是16位,按机器字节排序)
  • n - unsigned short (always 16 bit, big endian byte order)  n -不带有符号的短模式[short](通常是16位,按大endian字节排序)
  • v - unsigned short (always 16 bit, little endian byte order)  v -不带有符号的短模式[short](通常是16位,按小endian字节排序)
  • i - signed integer (machine dependent size and byte order)  i – 带有符号的整数(由大小和字节顺序决定)
  • I - unsigned integer (machine dependent size and byte order)  I – 不带有符号的整数(由大小和字节顺序决定)
  • l - signed long (always 32 bit, machine byte order)  l– 带有符号的长模式[long](通常是32位,按机器字节顺序)
  • L - unsigned long (always 32 bit, machine byte order)  L – 不带有符号的长模式[long](通常是32位,按机器字节顺序)
  • N - unsigned long (always 32 bit, big endian byte order)  N – 不带有符号的长模式[long](通常是32位,按大edian字节顺序)
  • V - unsigned long (always 32 bit, little endian byte order)  V– 不带有符号的长模式[long](通常是32位,按小edian字节顺序)
  • f - float (machine dependent size and representation)  f –浮点(由大小和字节顺序决定)
  • d - double (machine dependent size and representation)  d – 双精度(由大小和字节顺序决定)
  • x - NUL byte  x – 空字节[NUL byte]
  • X - Back up one byte  X- 后面一个字节[Back up one byte]
  • @ - NUL-fill to absolute position  @ - NUL- 添加到一个绝对位置[absolute position]
  php里的pack及unpack--转
  2009-03-15 22:11
  用了很久php了却很少有机会用php进行一些二进制操作。 最近用php写一个socket客户端连接一个用C++语言开发的游戏服务端。 服务器端开发人员使用了二进制的形式来定义协议的格式。协议格式如下:
  包头(2bytes)+加密(1byte)+命令码(2bytes)+帧内容
  1.包头的内容是记录帧内容的长度;
  2. 加密:0表示不加密,1表示加密;
  3. 命令码为服务端命令识别符号;
  一开始不了解php原来有pack可以来组装二进制包, 走了弯路,让服务端开发人员用C语言帮忙开发了的几个内存操作函数,按照协议规则返回二进制包,然后我将这几个方法编译成一组扩展函数供php使用。
  话归正题,本文是介绍如何使用pack和unpack这两个方法的。php官方手册举例太少,不能很容易理解,特别是那些格式化参数的使用。
  转摘的参数中文说明:
  pack/unpack 的摸板字符字符 含义
  a 一个填充空的字节串
  A 一个填充空格的字节串
  b 一个位串,在每个字节里位的顺序都是升序
  B 一个位串,在每个字节里位的顺序都是降序
  c 一个有符号 char(8位整数)值
  C 一个无符号 char(8位整数)值;关于 Unicode 参阅 U
  d 本机格式的双精度浮点数
  f 本机格式的单精度浮点数
  h 一个十六进制串,低四位在前
  H 一个十六进制串,高四位在前
  i 一个有符号整数值,本机格式
  I 一个无符号整数值,本机格式
  l 一个有符号长整形,总是 32 位
  L 一个无符号长整形,总是 32 位
  n 一个 16位短整形,“网络”字节序(大头在前)
  N 一个 32 位短整形,“网络”字节序(大头在前)
  p 一个指向空结尾的字串的指针
  P 一个指向定长字串的指针
  q 一个有符号四倍(64位整数)值
  Q 一个无符号四倍(64位整数)值
  s 一个有符号短整数值,总是 16 位
  S 一个无符号短整数值,总是 16 位,字节序跟机器芯片有关
  u 一个无编码的字串
  U 一个 Unicode 字符数字
  v 一个“VAX”字节序(小头在前)的 16 位短整数
  V 一个“VAX”字节序(小头在前)的 32 位短整数
  w 一个 BER 压缩的整数
  x 一个空字节(向前忽略一个字节)
  X 备份一个字节
  Z 一个空结束的(和空填充的)字节串
  @ 用空字节填充绝对位置
  string pack ( string $format [, mixed $args [, mixed $...]] )
  一些规则:
  1.每个字母后面都可以跟着一个数字,表示 count(计数),如果 count 是一个 * 表示剩下的所有东西。
  2.如果你提供的参数比 $format 要求的少,pack 假设缺的都是空值。如果你提供的参数比 $format 要求的多,那么多余的参数被忽略。
  下面还是用例子来说明用法会容易理解一点:
  关于Pack:
  下面的第一部分把数字值包装成字节:
  $out = pack("CCCC", 65, 66, 67, 68); # $out 等于"ABCD"
  $out = pack("C4", 65, 66, 67, 68); # 一样的东西
  下面的对 Unicode 的循环字母做同样的事情:
  $foo = pack("U4", 0x24b6, 0x24b7, 0x24b8, 0x24b9);
  下面的做类似的事情,增加了一些空:
  $out = pack("CCxxCC", 65, 66, 67, 68); # $out 等于 "AB\0\0CD"
  打包你的短整数并不意味着你就可移植了:
  $out = pack("s2", 1, 2);
  # 在小头在前的机器上是 "\1\0\2\0"
  # 在大头在前的机器上是 "\0\1\0\2"
  在二进制和十六进制包装上,count 指的是位或者半字节的数量,而不是生成的字节数量:
  $out = pack("B32", "...");
  $out = pack("H8", "5065726c"); # 都生成“Perl”
  a 域里的长度只应用于一个字串:
  $out = pack("a4", "abcd", "x", "y", "z"); # "abcd"
  要绕开这个限制,使用多倍声明:
  $out = pack("aaaa", "abcd", "x", "y", "z"); # "axyz"
  $out = pack("a" x 4, "abcd", "x", "y", "z"); # "axyz"
  a 格式做空填充:
  $out = pack("a14", "abcdefg"); # " abcdefg\0\0\0\0\0\0"
  关于unpack:
  array unpack ( string $format, string $data )
  $data = "010000020007";
  unpack("Sint1/Cchar1/Sint2/Cchar2",$data);
  ## array('int1'=&gt;1, 'char1'=&gt;'0','int2'=&gt;2,'char2'=&gt;7);
  最后本文开头讲到的协议使用pack/unpack 举例程序代码为 :
  $lastact = pack('SCSa32a32',0x0040, 0x00, 0x0006, $username, $passwd );
  unpack('Sint1/Cchar1/Sint2/Cchar2/',$lastmessage);

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359041-1-1.html 上篇帖子: 从魔兽看PHP设计模式 下篇帖子: php高手之路之—屠龙宝刀
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表