關於 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'];
相關文章
相關標籤/搜索