php 的pack方法

來源:互聯網
上載者:User
 

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

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。

//第三行: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);                          // ABCD

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.