关于 php 中 pack 、unpack、 ord 的理解和用法

pack函数说明:本函数用来将资料压缩打包到位的字符串之中。php

首先  pack的 格式 为  pack('最原始数据使用的格式,'原始数据'');网络

pack('a1','h')或者pack('a*','h');函数

每一个字母(好比上面的a)后面均可以跟着一个数字,表示count(计数)来解释成某种形式的重复计数或者长度(换算后字符长度发生了改变),具体状况取决于格式。除了a,A,b,B,h,H,P,和 Z 以外,全部格式的count 都是重复次数(也就是说 上面的这几个字符后面的“计数”指的是获取字符串的长度),ack('a*','h')字母(好比上面的a)后面均可以跟着一个数字,表示count(计数),解释成某种形式的重复计数或者长度,具体状况取决于格式。除了a,A,b,B,h,H,P,和 Z 以外,全部格式的count 都是重复次数(也就是说 上面的这几个字符后面的“计数”指的是获取字符串的长度),所以 pack 从 LIST 里吃进那么多数值(除了第一个参数,剩下的参数能够理解成都在一个列表中)。若是 count 是一个 *表示剩下的全部东西。【pack('a*',100,20) :只取第一个参数的全部字符  ,pack('C*',100,101,102):把这三个参数都换算,pack('Cf'',224,3.14,100)  :C:换算244,f:换算剩下全部的参数】。编码

 

理解:pack 返回的数据 都用经过 ASCII码换算事后的,若是单纯理解ASCII换算的话 ,能够用一个php函数  ord():返回字符串第一个字符的 ASCII 值。加密

好比 ord(‘h’)和ord(‘hello’)都是返回一个十进制数:114【占用三个字节】,而pack('a*','h')也返回114, 可是在ord的基础上对字节进行了 增长或者减小(也就是对位的增长减小)当前这个列子上没有增长也没减小   好比pack('C',100)  返回 一个字节为:d。指针

上面的"a" 指的是转成什么字符,“*”指的是剩下的全部东西,若是改为‘a1’的话 ,就是获取原始数据的第一个字符转成a格式的字符。code

下面是pack全部的格式(网上所有都是列出来的,虽然一看见这么多 觉着恶心):token

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 一个空结束的(和空填充的)字节串
@ 用空字节填充绝对位置ci

 

经过下面的代码 能够看出他们的不一样:字符串

//A字符 
$str=(pack("A*", "中国")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//H字符 
$str=(pack("H*", "fffe")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//C字符 
$str=(pack("C*", "55","56","57")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 
//i字符 短整形 32位 4个字节 64位8个字节 
$str=(pack("i", "100")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//s字符 短整形 2个字节 
$str=(pack("s", "100")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//l字符 长整形 4个字节 
$str=(pack("l", "100")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//f字符 单精度浮点 4个字节 
$str=(pack("f", "100")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


//d字符 双精度浮点 8个字节 
$str=(pack("d", "100")); 
echo $str,"=",strlen($str),"字节\n"; 
getAscill($str); 


function getAscill($str) 
{ 
$arr=str_split($str); 
foreach ($arr as $v) 
{ 
echo $v,"=",ord($v),"\n"; 
} 
echo "=============\r\n\r\n"; 
}

/*pack做用:节省空间、加密格式 */

$code = array(?
    "username" => array("A20", "张三adfb12"), 
    "pass" => array("A10", "asdf*#1"), 
    "age" => array("C", "23"), // 转成一个字节? 节省了空间
    "birthday" => array("I", "19900101"), // 转成4个字节,想象一下 若是第二个参数长度一直增大好比‘199001010001256325’ ,到那时就更能够看出节省的空间了(由于不论多大 都是占用4个字节)
    "email" => array("A50", "zhangsan@163.com")
); //进行了加密

$stream = join("\0", packByArr($code));

echo $stream, strlen($stream);

file_put_contents("c:/1.txt", $stream);
 // 将流保存起来便于下面读取?
function packByArr($arr)?
{
    $atArr = array();
    foreach ($arr as $k => $v)
    {
        $atArr[] = pack($v[0], $v[1]);
    } 
    return $atArr;
} 

function getAscill($str)
{
    $arr = str_split($str);
    foreach ($arr as $v)
    {
        echo $v, "=", ord($v), "\n";
    } 
}

Unpack解包 
解包须要按照,打包方式读取,该读取多长,该用什么类型读取,必须与打包规定同样。 

$code = array(?
    "username" => array("A20"), 
    "pass" => array("A10"), 
    "age" => array("C"), 
    "birthday" => array("I"), 
    "email" => array("A50")
);

$stream = file_get_contents("c:/1.txt");

var_dump(packByArr($stream, $code));

function packByArr($str, $code)
{
    $Arr = explode("\0", $str);
    
    $atArr = array();
    
    $i = 0;
    foreach ($code as $k => $v)
    {
        $atArr[$k] = unpack($v[0], $Arr[$i]);
        $i++;
    } 
    return $atArr;
}

 

$token="e3bc81ef8fa211a9edaaac2e0f7132d8";

$id=123;

$new_id=134343;

$model="image";

$msg = pack("NA40NN", strlen($token), $token, $id,$new_id);

print $msg;

$rs = unpack("NLength/A40token/Nid/Ncmsaid/A10model" , $msg);

if($rs==NULL){
    $rs = unpack("NLength/A40token/Nid/Ncmsaid" , $msg);
}

print_r($rs);

print $rs['id'];
相关文章
相关标签/搜索