我们先大略聊一下7bit的来源及事理。
下面这段话我也是网上看到的,说得很好,为了更贴近pdu实例,我轻微做了些修正:
7bit编码实际上是一种压缩编码,由于ASCII码(不包括扩展的ASCII) 其值都是小于0x80的,也便是说其最高位为0,那么最高位信息也便是说没故意义的,可以被忽略。而7-bit编码也正是关注到了这一点,利用最高位也来存储数据,其编码时一次将下一7位编码的后几位逐次移到前面,形成了新的8位编码。
那么这样的话,回到我们的例子,也便是说ASCII字符可以利用7位编码
首先将所有字符转换成7位编码,即只要去除最高位就行:
1 2 3 4
0110001 0110010 0110011 0110100
现在须要将没个字节补齐,也便是补到8位,
首先将1补齐,将2的末了一位补到1前面:00110001 011001 0110011 0110100
将2补齐,将3的末了两位不到2前面: 00110001 11011001 01100 0110100
将3补齐,将4的末了补到3前面: 00110001 11011001 10001100 0110
末了将4补齐,在最前面不上四个0: 00110001 11011001 10001100 00000110
这个时候1234字符串的编码就变为了: 31 d9 8c 06 该值恰好便是我们的短信内容!
下面开始上源码:
class CharsetConv{ / pdu编码 @param $codetype 编码办法 08:ucs-2,00:7bit @param $str 待转码的字符 @return 转码后的字符 / public function decode_pdu($codetype,$str){ switch($codetype){ case \"大众08\"大众://ucs-2 $smsok = $this->decode_ucs2($str); break; case \"大众00\"大众://7bit $smsok = $this->decode_7bit($str); break; default: $smsok = $str; } return $smsok; } private function encode_7bit($sms){ $smsa = str_split($sms, 1); foreach ($smsa as $k=>$sv) { $s = base_convert(ord($sv), 10, 2); if(strlen($s)<7){ $sv = \公众0\公众.$s; }else{ $sv = $s; } $smsa[$k] = $sv; } for($i=0;$i<count($smsa);$i++){ $j = $i+1; if($i < count($smsa)-1){ $bu[$j] = substr($smsa[$j],0-$j); $smsa[$i] = $bu[$j].$smsa[$i]; }else{ $buz = \"大众\"大众; for($k=0;$k<$j;$k++){ $buz .= \"大众0\公众; } $smsa[$i] = $buz.$smsa[$i]; } $smsa[$i] = substr($smsa[$i],0,8); } foreach($smsa as $k=>$sav){ $hexres = base_convert($sav, 2, 16); $smsa[$k] = str_pad($hexres,2,\"大众0\"大众,STR_PAD_LEFT); } $smscontent = implode(\公众 \"大众,$smsa); return strtoupper($smscontent); } }
本文只谈论了7bit的编码,如果有朋友对ucs-2编码感兴趣,我们下次再讲。
利用方法:
$conv = new CharsetConv();$content = $conv->encode_pdu(\"大众00\"大众,$sms);//内容为英文,编码格式7bit
上面代码中,$sms为待编码的字符,$content为编码后的7bit内容。