php 的pack方法 概括總結

今天在弄這個pack方法,可是真不知道如何寫下來,感受很紛亂php

pack--壓縮資料到位字符串之中。
語法:string pack(string format, mixed [args]...);
參數一:format參數表示資料用什麼方式讀取到
參數二:將要壓縮的資料。

參數一 的種類
a 將字符串空白以 NULL 字符填滿
A 將字符串空白以 SPACE 字符 (空格) 填滿
h 十六進位字符串,低位在前
H 十六進位字符串,高位在前
c 有號字符
C 無號字符
s 有號短整數 (十六位,依計算機的位順序)
S 無號短整數 (十六位,依計算機的位順序)
n 無號短整數 (十六位, 高位在後的順序)
v 無號短整數 (十六位, 低位在後的順序)
i 有號整數 (依計算機的順序及範圍)
I 無號整數 (依計算機的順序及範圍)
l 有號長整數 (卅二位,依計算機的位順序)
L 無號長整數 (卅二位,依計算機的位順序)
N 無號短整數 (卅二位, 高位在後的順序)
V 無號短整數 (卅二位, 低位在後的順序)
f 單精確浮點數 (依計算機的範圍)
d 倍精確浮點數 (依計算機的範圍)
x 空位
X 倒回一位
@ 填入 NULL 字符到絕對位置

上面參數一得總結來自於網絡,不知道是哪一個翻譯翻得,總之我我的不推薦看。下面是php手冊上面的內容(全英文的,雖然我也看不懂,可是一個單詞一個單詞的翻譯去理解,也比看上面的翻譯強)

a -- NUL-padded string
A -- SPACE-padded string
h -- Hex string, low nibble first
H -- Hex string, high nibble first
c -- signed char
C -- unsigned char
s -- signed short (always 16 bit, machine byte order)
S -- unsigned short (always 16 bit, machine byte order)
n -- unsigned short (always 16 bit, big endian byte order)
v -- unsigned short (always 16 bit, little endian byte order)
i -- signed integer (machine dependent size and byte order)
I -- unsigned integer (machine dependent size and byte order)
l -- signed long (always 32 bit, machine byte order)
L -- unsigned long (always 32 bit, machine byte order)
N -- unsigned long (always 32 bit, big endian byte order)
V -- unsigned long (always 32 bit, little endian byte order)
f -- float (machine dependent size and representation)
d -- double (machine dependent size and representation)
x -- NUL byte
X -- Back up one byte
@ -- NUL-fill to absolute position

====================H 和 h========================
-------------------------H -- h ------------------------------
先看中文翻譯
H 十六進位字符串,高位在前
h 十六進位字符串,低位在前

再看英文
h -- Hex string, low nibble first 十六進制,低位在前以半字節爲單位(上面的翻譯少了半字節,這個半字節很重要,nibble就是半字節的意思)
H -- Hex string, high nibble first 十六進制,高位在前以半字節爲單位瀏覽器


H是一次是4位的讀取,一個十六位進制是佔4位,因此H是一次4位,H2是一次8位(即一個字節)。
echo pack("H",0x4);
echo pack("H2",65);
echo pack("H2",0x41);
echo pack("H2",」41「);
echo pack("H2H2", 0x41, 0x42);
echo pack("h2h2", 0x41,0x42); `
echo pack("H3", 124);
echo pack("h3",124);網絡

輸出以下
@
e
e
A
ef
Vf




//第一行:pack("H",0x4);將一個十六進制(4位)以十六進制的方式讀取而後寫入到字符串中。由於0x4是4位,
0x4轉化爲十進制爲4。而一個字節是8位,因此會自動補充位一個字節8位的長度,後面4位補充爲0000(記住!但凡要進行pack方法的H前,必須先將字節補充完整)。因此十進制爲40(爲何要轉化爲十進制去在讀取,我也不知道,可能pack方法開發者就是這麼寫的),十進制40以H十六進制的方式讀取,就是0x40,轉換成ascii碼就爲@。編碼

//第二行:pack("H2",65);65是十進制(H默認是讀取讀取十進制,以十六進制的方式讀取),因此65被H後爲0x65,轉化爲ascii碼就是e。spa

//第三行:pack("H2",0x41);0x41是十六進制,H2表示一次讀取8位(H默認是讀取讀取十進制,以十六進制的方式讀取),0x41轉化爲十進制爲65,65被H後爲0x65,轉化爲ascii碼就是e。

//第四行:pack("H2",」41「);"41"爲字符串,H2表示讀取1個8位,可是(H默認是讀取讀取十進制,以十六進制的方式讀取,因此字符串41就被H默認轉換爲十進制41),十進制41被H後爲0x41,轉化爲ascii碼就是A。

//第五行:pack("H2H2", 0x41, 0x42);0x41和0x42一共是十六位,H2H2表示讀取兩個8位,轉化爲十進制爲65和66,65被H後就是0x65,66被H就是0x66,轉化爲ascii碼就是分別是ef。

//第六行:pack("h2h2", 0x41,0x42);0x41和0x42是兩個八位,h十六進位字符串,低位在前。h和H是幾乎是同樣的只是一個先後排序的問題。H是高位在前,h是低位在前。0x41和0x42轉化爲十進制65和66,。這裏讀取後跟H不同,h是低位在前,H是高位在前。這裏來作一個比較,以下:

讀取前十六進制 0x41 0x42
讀取前十進制 65 66
H讀取後十六進制 0x65 0x66
h讀取後十六進制 0x56 0x66
H讀取後二進制 01100101 01100110 高位在前 以一次H讀取對象爲基礎,4位爲單位,進行高低互換
h讀取後二進制 01010110 01100110 低位在前 以一次h讀取對象爲基礎,4位爲單位,進行高低互換

h按16進制讀取後分別爲二進制01010110和01100110轉化爲十六進制56和66,轉化爲ascii碼爲Vf。

//第七行:pack("H3", 124);由於要首先要將字節補充完整,所以補充完整後爲1240。1240是十進制(H默認是讀取讀取十進制,以十六進制的方式讀取),因此1240被H之後打到的是0x1240,轉換爲2進制的話就爲0001 0010 0100 0000,轉換爲16進制就是0x1240,而瀏覽器這裏是以ascii碼讀取的,因此是8位一次的翻譯,因此0x1240被分割成0x12和0x40,0x40是@,0x12在ascii表裏能夠看到是(device control 2) 設備控制2,這個東西在ie8中顯示出來就是上下雙向箭頭。而在ie6,ie7瀏覽器上由於使用的不一樣的編碼方式,而顯示出不一樣的字符。

//第八行:pack("h3",124);由於h是低位在前,並且又是1個半字節(記住!但凡要進行pack方法的H前,必須先將字節補充完整),而後再,咱們來對比一下h與H,
讀取前十六進制 0x7C
讀取前十進制 1240
H讀取後十六進制 0x1240
h讀取後十六進制 0x0421
H讀取後二進制 0001001001000000 高位在前 以一次H讀取對象爲基礎,4位爲單位,進行高低互換
h讀取後二進制 0000010000100001 低位在前 以一次h讀取對象爲基礎,4位爲單位,進行高低互換

0000 0100 0010 0001 或者 0x0421,分紅0x04和0x21,在ie8中以ascii碼錶示出來就是如上所示


=================V 和 N====v 和 n=======================
-------------------------V - N-----------------------
先看中文翻譯
V 無號短整數 (卅二位, 低位在後的順序)
N 無號短整數 (卅二位, 高位在後的順序)


再看英文
V -- unsigned long (always 32 bit, little endian byte order) 無符號長整型(老是32位,低地址存放最低有效字節)(根據金山詞霸的解釋)
N -- unsigned long (always 32 bit, big endian byte order) 無符號長整形(老是32位,高地址存放最低有效字節)(根據金山詞霸的解釋)


下面解釋 little endian 和 big endian
big endian -- 是指低地址存放最高有效字節
little endian -- 是指低地址存放最低有效字節翻譯

好比:a = 0x05060708
0x05060708
高端<---低端

在BIG-ENDIAN的狀況下存放爲:
由於低端地址存放高端有效字,08是最低有效字放在高端地址
字節號 0 1 2 3 ··· ···
低端地址 高端地址
----------------------------------------->
數據 05 06 07 08 ··· ···


在LITTLE-ENDIAN的狀況下存放爲:
由於低地址存放最低有效字節,08是最低有效字放在低端地址
字節號 0 1 2 3 ··· ···
低端地址 高端地址
----------------------------------------->
數據 08 07 06 05 ··· ···

由於內存都是從低端地址讀起,由於讀取內存數據通常使用地址指針,讀一個地址在加一個偏移量。因此這個內存little-endian 與 big-endian 決定了數據讀取出來的順序,並非想上面那個中文翻譯的那樣子(什麼低位在後的順序,我是服了,翻譯的真讓我受不了)。


下面舉幾個V的例子
echo "1 ".pack("V",0x65666768696A6B);echo "<br />";
echo "2 ".pack("V",0x666768696A6B6C);echo "<br />";
echo "3 ".pack("V",0x6768696A6B6C6D);echo "<br />";

顯示出來爲
// kjih 01101011 01101010 01101001 01101000
// k j i h
// lkji 01101100 01101011 01101010 01101001
// l k j i
// mlkj 01101101 01101100 01101011 01101010
// m l k j

N的例子
echo "4 ".pack("N",0x65666768696A6B);echo "<br />";
echo "5 ".pack("N",0x666768696A6B6C);echo "<br />";
echo "6 ".pack("N",0x6768696A6B6C6D);echo "<br />";

顯示出來爲
// hijk 01101000 01101001 01101010 01101011
// h i j k
// ijkl 01101001 01101010 01101011 01101100
// i j k l
// jklm 01101010 01101011 01101100 01101101
// j k l m

-------------------v - n----------------
先看中文翻譯
v 無號短整數 (十六位, 低位在後的順序)
n 無號短整數 (十六位, 高位在後的順序)


再看英文
v -- unsigned short (always 16 bit, little endian byte order) 無符號短整型(老是16位,低地址存放最低有效字節)(根據金山詞霸的解釋)
n -- unsigned short (always 16 bit, big endian byte order) 無符號短整形(老是16位,高地址存放最低有效字節)(根據金山詞霸的解釋)


不用舉例子了,這個跟V和N的區別就是16位和32位的區別。


-------------------關於V - N溢出的問題--------------------------



================ a ===================
先看中文翻譯
a 一個填充空的字節串

再看英文翻譯
指針

a NUL-padded string
a NUL-padded string
a NUL - padded string

下面是例子:
echo pack("a",65)."<br />";
echo pack("a2",65)."<br />";
echo pack("a2",65,66)."<br />";
echo pack("a2a2",65,66)."<br />";
echo pack("a","65")."<br />";
echo pack("a2","65")."<br />";
echo pack("a",0x65)."<br />";
echo pack("a1",0x65)."<br />";
echo pack("a2",0x65)."<br />";
echo pack("a3",0x65)."<br />";

輸出爲:
6
65
"報錯"
65
6
65
1
1
10
101

由上面例子可知,這個該死的a,是以十進制的方式讀取的,無論是字符仍是十六進制都是先轉換爲十進制讀取的,a1是讀取一位十進制(也不知道是多少位),a2是讀取二位十進制(也不知道是多少位),a3是讀取三位十進制(也不知道是多少位)。若是是十六進制,就先轉換成十進制,如上面的0x65轉換成101,而後用a3讀取後顯示出來就是101。

-------------------------------------------------------------------------------------------------------

echo pack("cccc", 0x41, 0x42, 0x43, 0x44); // ABCD
echo pack("cccc", 65, 66, 67, 68); // ABCD
echo pack("c4", 0x41, 0x42, 0x43, 0x44); // ABCD
echo pack("c4", 65, 66, 67, 68); // ABCDorm

待續對象

相關文章
相關標籤/搜索