php函數手冊(自製二進位“資料庫”)

來源:互聯網
上載者:User

標籤:

引言

pack、unpack函數,如果沒有接觸過socket,這個可能會比較陌生,這兩個函數在socket互動的作用是組包,將資料裝進一個二進位字串,和對二進位字串中的資料進行解包,這個裡面有好多種格式,具體的格式可以去查查官方的手冊(或者等看完本篇文章之後,去調用介面查看),我這裡主要用了pack(“N”,int),pack(“a”,str)以及他們兩個對應的解包函數,N在手冊中的解釋是下面這個,佔4個位元組,大端方式(其實就是低位在前還是在後的問題)。a是對字串進行打包,不夠指定的數值的時候用NULL(\0,或者說assic碼0對應的字元)填充。

N - unsigned long (always 32 bit, big endian byte order)

a - NUL-padded string

我將用這個打包解包函數做一個函數手冊查詢小工具,或者可以說是一個自製小型位元據庫。

 

設計資料格式

在做這個二進位檔案資料庫的時候我會建立兩個檔案,一個是索引檔案,一個是要查詢的資料的檔案,分別看看他們的結構:

說明中括弧內的數字為所佔位元組(bytes)數,"~"波浪線表示所佔位元組數不確定

資料檔案,第一個php是一個正式的字串"php",佔4個位元組,後面跟著版本說明,長度不確定(這個長度可以從後面的index檔案中擷取),接下來後面是儲存資訊的主體了。首先是一個函數名長度lenName佔4個位元組,接下來是函數名稱,長度不確定,有前面的lenName對應的值確定,接下來是lenVal佔4個位元組,後面跟的是具體的函數說明內容,長度有前面的lenVal對應的值確定。

          內容儲存格式定義++++++++++++++++++++++++++++++++++++++|php(4)        |版本說明(~)           |++++++++++++++++++++++++++++++++++++++|lenName(4)    |函數名稱(~)           |++++++++++++++++++++++++++++++++++++++|lenVal(4)     |函數內容(~)           |++++++++++++++++++++++++++++++++++++++            ......

索引檔案,索引檔案就比較簡單了,其中全部儲存了上面的隱藏檔中每個函數開始的指標位置,每個位置佔用4個位元組。

索引格式定義++++++++++++++++++++++++++++++++++++++|position(4)                         |++++++++++++++++++++++++++++++++++++++            ......

 

查詢的實現

由於隱藏檔中的內容是按照函數名順序排序儲存的,索引也是按照函數儲存的順序儲存的,所以擷取起來很方便,直接使用二分法就可以很輕鬆的擷取到想要的函數

在查詢的時候主要使用了下面幾個方法:

第一、從制定位置擷取一條索引的值(也就是對應的函數隱藏檔的指標位置)

/** * 從索引檔案中擷取一條記錄的位置 * @param 索引檔案中的開始位置,從開始位置擷取四個位元組為一個函數說明的開始位置 * @return 返回該索引位置所對應的儲存位置指標位移量 */private function _getOneIndex($pos){    fseek($this->_indexHandle, $pos);    $len = unpack("Nlen", fread($this->_indexHandle, 4));    return $len[‘len‘];}

第二、從指定的指標位移位置擷取一條len(4)+val(~)格式的內容

/** * 從制定的指標位移量擷取一個len+val型的內容 * @param $pos 檔案的指標位移量 * @return 返回數組,包括長度和值 */private function _getStoreLenValFormat($pos){    fseek($this->_storeHandle, $pos);    $len = unpack("Nlen", fread($this->_storeHandle, 4));    $len = $len[‘len‘];    $val = fread($this->_storeHandle, $len);    return array    (        ‘len‘ => $len,        ‘value‘ => $val,    );}

第三、擷取制定函數的說明,這個也是最主要的一部分,使用二分法從資料檔案中擷取一條記錄

/** * 擷取函數內容 * @param 要尋找的函數名稱 * @return 返回函數說明的json字串 */public function get($func){    if(!$this->isInit())        return;    $begin = 0;    $end = filesize($this->_indexFile)/4;    $ret = ‘[]‘;    while($begin < $end){        $mid = floor(($begin + $end)/2);        $pos = $mid*4; //$mid只是指標變數的位置,還需要乘上指標的長度4        $pos = $this->_getOneIndex($pos);        $name = $this->_getStoreLenValFormat($pos);        $flag = strcmp($func, $name[‘value‘]);        if($flag == 0){            $val = $this->_getStoreLenValFormat($pos+4+$name[‘len‘]);            $ret = $val[‘value‘];            break;        }elseif($flag < 0){            $end = $end == $mid ? $mid-1 : $mid;        }else{            $begin = $begin == $mid ? $mid+1 : $mid;        }    }    return $ret;}

使用很簡單,只需包含類庫檔案和隱藏檔資料庫,然後調用幾句代碼就可以

<?phpinclude_once("./manual/phpManual.php");$t = new phpManual();$t->init(‘zh‘);echo $t->get("unpack");

輸出的是json字串,轉化後如下所示,其中有詳細的說明,以及簡潔的例子

{    "name": "unpack",    "desc": "Unpack data from binary string.",    "long_desc": "Unpacks from a binary string into an array according to the given `format`.\\n\\nThe unpacked data is stored in an associative array. To accomplish this you have to name the different format codes and separate them by a slash /. If a repeater argument is present, then each of the array keys will have a sequence number behind the given name.",    "ver": "PHP 4, PHP 5",    "ret_desc": "Returns an associative array containing unpacked elements of binary string.",    "seealso": [        "pack"    ],    "url": "function.unpack",    "class": null,    "params": [        {            "list": [                {                    "type": "string",                    "var": "$format",                    "beh": 0,                    "desc": "See pack() for an explanation of the format codes."                },                {                    "type": "string",                    "var": "$data",                    "beh": 0,                    "desc": "The packed data."                }            ],            "ret_type": "array"        }    ],    "examples": [        {            "title": "unpack() example",            "source": "$binarydata = \"\\x04\\x00\\xa0\\x00\";\n$array = unpack(\"cchars/nint\", $binarydata);",            "output": null        },        {            "title": "unpack() example with a repeater",            "source": "$binarydata = \"\\x04\\x00\\xa0\\x00\";\n$array = unpack(\"c2chars/nint\", $binarydata);",            "output": null        },        {            "title": "unpack() example with unnamed keys",            "source": "$binarydata = \"\\x32\\x42\\x00\\xa0\";\n$array = unpack(\"c2/n\", $binarydata);\nvar_dump($array);",            "output": null        }    ]}

最後再附上目錄結構:

+phpManual    +manual        +phpManual            +zh                |_manualIndex                |_manualStore        |_phpManual.php    |_test.php

 

這個是程式的完整地址:

完整例子地址

 

參考

https://github.com/aizuyan/php-doc-parser 從這裡拿到的phpmanual的全部資料

  

本文著作權歸作者iforever([email protected])所有,未經作者本人同意禁止任何形式的轉載,轉載文章之後必須在文章頁面明顯位置給出作者和原文串連,否則保留追究法律責任的權利。

php函數手冊(自製二進位“資料庫”)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.