相关知识储备
GB2312编码范围:A1A1 - FEFE ,其中汉字编码范围:B0A1-F7FE.
GB2312编码是第一个汉字编码国家标准,共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母,希腊字母,日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。
分区表示
GB2312 编码对所收录字符进行了“分区”处理,共94个区,每区含有94个位,共8836个码位。这种表示方法也称为区位码。
01-09区收录除汉字外的682个字符。
10-15区位空白区,没有使用。
16-55区收录了3755个一级汉字,按拼音排序。
56-87区收录了3008个二级汉字,按部首/笔画排序。
88-94区为空白区,没有使用。
举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601
双字节编码
GB2312 规定对收录的每个字符采用两个字节表示,第一个字节为 “高字节”,对应94个区;第二个字节为“低字节”,对应94个位。所以它的区位码范围是:0101-9494。 区号和位号分别加上0xA0 就是GB2312编码。
例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。
GB2312编码范围:A1A1-FEFE,其中汉字的编码范围为B0A1-F7FE,第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)。
相关计算
区位码、国标码与机内码的转换关系方法:
(1)区位码先转换成十六进制数表示
(2)区位码的十六进制表示)+2020H=国标码;
(3)国标码+8080H=机内码
举例:以汉字“大”为例,“大”字的区内码为2083
1、区号为20,位号为83
2、将区位号2083转换为十六进制表示为1453H
3、1453H+2020H=3473H,得到国标码3473H
4、3473H+8080H=B4F3H,得到机内码为B4F3H
(3)国标码+8080H=机内码
举例:以汉字“大”为例,“大”字的区内码为2083
1、区号为20,位号为83
2、将区位号2083转换为十六进制表示为1453H
3、1453H+2020H=3473H,得到国标码3473H
4、3473H+8080H=B4F3H,得到机内码为B4F3H
PHP代码实现
<?php //国标码与区位码转换常量 $GB_SP_DIFF = 160; //存放国标一级汉字不同读音的起始 区位码 $secPosValueList = array(1601, 1637, 1833, 2078,2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600); //存放国标一级汉字不同读音的起始区位码对应读音 $firstLetter = array('a', 'b', 'c', 'd', 'e', 'f','g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x', 'y', 'z'); $string = "大家好"; echo $string.'<br/>'; $string=iconv( "UTF-8", "gb2312//IGNORE" , $string); $result = array(); //十进制 for($i=0;$i<strlen($string);$i++){ if(ord($string[$i])>127){ $result[] = (ord($string[$i])-$GB_SP_DIFF).''.(ord($string[++$i])-$GB_SP_DIFF); //从十进制 -160 得到区位码 } } //将区位码转对应的读音 $str=''; for($i=0;$i<count($result);$i++){ $j=getLetter($secPosValueList,$result[$i],count($secPosValueList),0); $str.=$firstLetter[$j]; } echo '首字母:'.$str; //二分查找 function getLetter($arr,$val,$hight,$low){ while($low <= $hight){ $mid = ceil($low + ($hight - $low) / 2); if($arr[$mid] <= $val && $arr[$mid+1] >$val){ return $mid; }elseif($arr[$mid] > $val){ $hight = $mid -1; }else{ $low = $mid +1; } } return -1; } ?>
运行结果:
大家好
首字母:djh