2010-07-03 20:14 PHP pack和unpack函數詳解

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: [email protected]

*  

* 一下文件存儲如下幾個字段

* 姓名: 長度 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' => '[email protected]');

$data = new Person_Data();

$data->openDb('./wps.db');

//$data->writeRecord($me);

print_r($data->read(1));

以上文件運行了兩側,寫入了兩行記錄,最後我讀取第二行記錄(索引自然從 1 開始)

運行一切正常:

Array

(

     [name] => 張心靈

     [age] => 23

     [email] => [email protected]

)

雙就一個字!

翻譯:

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);

來自: http://hi.baidu.com/sgooo/blog/item/a6e73cf0b689a5a6a50f52ed.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章