PHP資料壓縮、加解密(pack, unpack)

來源:互聯網
上載者:User
網路通訊、檔案儲存體中經常需要交換資料,為了減少網路通訊流量、檔案儲存體大小以及加密通訊規則,經常需要對資料進行雙向加解密以保證資料的安全。PHP中實現此功能主要需要使用的函數主要是pack及unpack函數
pack

壓縮資料到位字串之中。

文法: string pack(string format, mixed [args]...);

傳回值: 字串本函數用來將資料壓縮打包到位的字串之中。
a - NUL- 字串填滿[padded string] 將字串空白以 NULL 字元填滿A - SPACE- 字串填滿[padded string]h – 十六進位字串,低“四位元”[low nibble first] (低位在前)H - 十六進位字串,高“四位元”[high nibble first](高位在前)c – 帶有符號的字元C – 不帶有符號的字元s – 帶有符號的短模式[short](通常是16位,按機器位元組順序)S – 不帶有符號的短模式[short](通常是16位,按機器位元組排序)n -不帶有符號的短模式[short](通常是16位,按大endian位元組排序)v -不帶有符號的短模式[short](通常是16位,按小endian位元組排序)i – 帶有符號的整數(由大小和位元組順序決定)I – 不帶有符號的整數(由大小和位元組順序決定)l– 帶有符號的長模式[long](通常是32位,按機器位元組順序)L – 不帶有符號的長模式[long](通常是32位,按機器位元組順序)N – 不帶有符號的長模式[long](通常是32位,按大edian位元組順序)V– 不帶有符號的長模式[long](通常是32位,按小edian位元組順序)f –浮點(由大小和位元組順序決定)d – 雙精確度(由大小和位元組順序決定)x – 空位元組[NUL byte]X- 後面一個位元組[Back up one byte](倒回一位)

unpack

解壓縮位字串資料。

文法: string pack(string format, mixed [args]...);

傳回值: 數組本函數用來將位的字串的資料解壓縮。本函數和 Perl 的同名函數功能用法完全相同。
案例一、pack實現縮減檔案資料存放區大小
<?php//儲存整數1234567890file_put_contents("test.txt", 1234567890);
此時test.txt的檔案大小是10byte。注意此時檔案大小是10位元組,實際佔用空間大小是1KB。上面儲存的整數實際是以字串形式儲存於檔案test.txt中。但如果以整數的二進位字串存jy儲,將會縮減至4byte。
<?phpprint_r(unpack("i", file_get_contents("test.txt")));
案例二、資料加密以字串形式儲存一段有意義資料,7-110-abcdefg-117。字元"-"分割後,第一位表示字串長度,第二位表示儲存位置,第三位表示實際儲存的字串,第四位表示結尾位置。
<?phpfile_put_contents("test.txt", "7-110-abcdefg-117");
上述方法缺點:一、資料存放區大小二、資料以明文方式儲存,如果是任何敏感資訊,都可能造成不安全訪問。三、檔案儲存體大小,以不規則方式遞增。加密:
<?phpfile_put_contents("test.txt", pack("i2a7i1", 7, 110, "abcdefg", 117));
儲存一段資料,加密格式為:整數2位長度字串10位長度整數1位長度。優點:一、資料大小最佳化二、在不知道"i2a7i1"這樣的壓縮格式時,即使拿到檔案,也無法正確讀出二進位檔案轉化為明文。三、資料增加時,檔案儲存體大小是等量遞增。每次都是以19byte遞增。案例三、key-value型檔案儲存體儲存產生的檔案為兩個:索引檔案,資料檔案檔案中資料存放區的格式如:代碼實現:
<?phperror_reporting(E_ALL);class fileCacheException extends Exception{}//Key-Value型檔案儲存體class fileCache{     private $_file_header_size = 14;     private $_file_index_name;     private $_file_data_name;     private $_file_index;//索引檔案控制代碼     private $_file_data;//資料檔案控制代碼     private $_node_struct;//索引結點結構體     private $_inx_node_size = 36;//索引結點大小     public function __construct($file_index="filecache_index.dat", $file_data="filecache_data.dat"){          $this->_node_struct = array(               'next'=>array(1, 'V'),               'prev'=>array(1, 'V'),              'data_offset'=>array(1,'V'),//資料存放區起始位置              'data_size'=>array(1,'V'),//資料長度              'ref_count'=>array(1,'V'),//引用此處,模仿PHP的引用計數銷毀模式              'key'=>array(16,'H*'),//儲存KEY          );          $this->_file_index_name = $file_index;          $this->_file_data_name = $file_data;          if(!file_exists($this->_file_index_name)){               $this->_create_index();          }else{               $this->_file_index = fopen($this->_file_index_name, "rb+");          }          if(!file_exists($this->_file_data_name)){               $this->_create_data();          }else{               $this->_file_data = fopen($this->_file_data_name, "rb+");//二進位儲存需要使用b          }     }     //建立索引檔案     private function _create_index(){          $this->_file_index = fopen($this->_file_index_name, "wb+");//二進位儲存需要使用b          if(!$this->_file_index)                throw new fileCacheException("Could't open index file:".$this->_file_index_name);          $this->_index_puts(0, '<'.'?php exit()?'.'>');//定位檔案流至起始位置0, 放置php標記防止下載          $this->_index_puts($this->_file_header_size, pack("V1", 0));     }     //建立隱藏檔     private function _create_data(){          $this->_file_data = fopen($this->_file_data_name, "wb+");//二進位儲存需要使用b          if(!$this->_file_index)                throw new fileCacheException("Could't open index file:".$this->_file_data_name);          $this->_data_puts(0, '<'.'?php exit()?'.'>');//定位檔案流至起始位置0, 放置php標記防止下載     }     private function _index_puts($offset, $data, $length=false){          fseek($this->_file_index, $offset);          if($length)          fputs($this->_file_index, $data, $length);          else          fputs($this->_file_index, $data);     }     private function _data_puts($offset, $data, $length=false){          fseek($this->_file_data, $offset);          if($length)          fputs($this->_file_data, $data, $length);          else          fputs($this->_file_data, $data);     }     /**     * 檔案鎖     * @param $is_block 是否獨佔、阻塞鎖     */     private function _lock($file_res, $is_block=true){          flock($file_res, $is_block ? LOCK_EX : LOCK_EX|LOCK_NB);     }     private function _unlock($file_res){          flock($file_res, LOCK_UN);     }     public function add($key, $value){          $key = md5($key);          $value = serialize($value);          $this->_lock($this->_file_index, true);          $this->_lock($this->_file_data, true);          fseek($this->_file_index, $this->_file_header_size);          list(, $index_count) = unpack('V1', fread($this->_file_index, 4));          $data_size = filesize($this->_file_data_name);          fseek($this->_file_data, $data_size);          $value_size = strlen($value);          $this->_data_puts(filesize($this->_file_data_name), $value);          $node_data =           pack("V1V1V1V1V1H32", ($index_count==0) ? 0 : $index_count*$this->_inx_node_size, 0, filesize($this->_file_data_name), strlen($value), 0, $key);          $index_count++;          $this->_index_puts($this->_file_header_size, $index_count, 4);          $this->_index_puts($this->get_new_node_pos($index_count), $node_data);          $this->_unlock($this->_file_data);          $this->_unlock($this->_file_index);     }     public function get_new_node_pos($index_count){          return $this->_file_header_size + 4 + $this->_inx_node_size * ($index_count-1);     }     public function get_node($key){          $key = md5($key);          fseek($this->_file_index, $this->_file_header_size);          $index_count = fread($this->_file_index, 4);          if($index_count>0) {               for ($i=0; $i < $index_count ; $i++) {                     fseek($this->_file_index, $this->_file_header_size + 4 + $this->_inx_node_size * $i);                    $data = fread($this->_file_index, $this->_inx_node_size);                    $node = unpack("V1next/V1prev/V1data_offset/V1data_size/V1ref_count/H32key", $data);                    if($key == $node['key']){                         return $node;                    }               }          }else{               return null;          }     }     public function get_data($offset, $length){          fseek($this->_file_data, $offset);          return unserialize(fread($this->_file_data, $length));     }}//使用方法$cache = new fileCache();$cache->add('abcdefg' , 'testabc');$data = $cache->get_node('abcdefg');print_r($data);echo $cache->get_data($data['data_offset'], $data['data_size']);
案例四、socket通訊加密通訊雙方都定義好加密格式:例如:
$LOGIN = array(     'COMMAND'=>array('a30', 'LOGIN'),     'DATA'=>array('a30', 'HELLO'));$LOGOUT = array(     'COMMAND'=>array('a30', 'LOGOUT'),     'DATA'=>array('a30', 'GOOD BYE'));$LOGIN_SUCCESS = array(     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),     'DATA'=>array('V1', 1));$LOGOUT_SUCCESS = array(     'COMMAND'=>array('a30', 'LOGIN_SUCCESS'),     'DATA'=>array('V1', time()));
伺服器端與用戶端根據解析COMMAND格式,找到對應的DATA解碼方式,得到正確的資料

聯繫我們

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