varint算法——本质上是牺牲最高位作为标识数据结束位,达到变长编码,说白了就是贪心的分割位
varint算法,摘自:http://blog.csdn.net/liaoquesg/article/details/50897327
最近在看《大规模WEB服务开发技术》这本书中。书中提到“可变长字节码算法”的压缩数据的算法,以达到压缩数据,减少磁盘IO。
可变长字节码算法:
任意一个字节的最高位(下标7)均只作为标志位,而且根据字节所在位置需要乘以128的相应幂次;(我觉得这个算法只能用作自然数的压缩)
这是他的伪代码
仔细研究后,我翻译成PHP版的:
<?php function codeNumber($n){ $bytes = []; while (true){ array_unshift($bytes, bcmod($n, 128)); if($n < 128){ break; }else{ $n = intval($n/128); } } $bytes[count($bytes) - 1] += 128; return $bytes; } function encode($numbers){ $bytestream = []; foreach ($numbers as $n){ $bytestream = array_merge($bytestream, codeNumber($n)); } return $bytestream; } function decode($bytestream){ $numbers = []; $n = 0; for ($i = 0; $i < count($bytestream); $i++){ if($bytestream[$i] < 128){ $n = 128 * $n + $bytestream[$i]; }else{ $n = 128 * $n + ($bytestream[$i] - 128); array_push($numbers, $n); $n = 0; } } return $numbers; } $a = encode([5, 130, 288]); var_dump($a); var_dump(decode($a)); 打印出来的内容是: array(5) { [0]=> int(133) [1]=> string(1) "1" [2]=> int(130) [3]=> string(1) "2" [4]=> int(160) } array(3) { [0]=> int(5) [1]=> int(130) [2]=> int(288) } //写二进制 $h = fopen('ejz3.txt', 'wb'); foreach ($a as $k => $v) { $str3 = pack('H*', sprintf("%02x", $v)); fwrite($h, $str3); } fclose($h); //读二进制 $str2 = file_get_contents('ejz3.txt'); $str2 = unpack("H*", $str2); $value = str_split($str2[1], 2); foreach ($value as $k => $v) { $value[$k] = base_convert($v, 16, 10); }