$str = '聯運車輛交接樞紐';
var_dump(big52gb($str,'GB2312'));exit;
function big52gb($str,$table)
{
return trans($fp = fopen($table,'r'), $str, $table);
}
function trans(& $fp, $str, $from)
{
if($from == 'GB2312') {
$to = 'BIG5';
} else {
$from = 'BIG5';
$to = 'GB2312';
}
$out = "";
for($i = 0; $i < mb_strlen($str, "UTF-8"); $i ++)
{
$t = mb_substr($str, $i, 1, "UTF-8");
//如果t的长度<2说明是ascii字符或某个汉字的一部分,ascii字符在各种编码中都一致,故而追加到后面即可
if(strlen($t)<2)
{
$out .= $t;
continue;
}
$tmp = mb_convert_encoding($t, $from, "UTF-8");
if(strlen($tmp) < 2) {//这块儿<2说明:此字符在utf8下但不在$from下,故不用在码表里面查找对应的$to编码,直接追加
$out .= $t;
continue;
}
//到此说明此utf-8字符在gb2312或big5下有对应字符
$x = ord($tmp[0]);
$y =ord($tmp[1]);
/**
说明在中文的范围内,中文简体的高字节是a1-fe,中文繁体的高字节范围是a0-fe,但真实的编码开始是a1
故此范围可确保是中文
*/
if($x>=hexdec('a1') && $x<=hexdec('fe'))
{
if($x == 161 && $y == 64)
{
$out .= $t;continue;
}
$pos = ($x-160)*510+($y-1)*2;
if($pos < 1) {//说明此gb2312字符在此码表中无对应的big5,反之亦然,故不用转,追加
$out .= $t;
continue;
}
fseek($fp, $pos);
$trans= fread($fp,2);
$trans = mb_convert_encoding($trans, "UTF-8", $to);
$out .= $trans;
}
else {
{
/**
此处为什么要加这个else呢?按道理说到这里就说明一定是gb2312或big5了,但编码这块有些不是那么准确,
比如'錇'字,它不属于gb2312和big5,但属于gbk和big5-hkscs.但是在$tmp = mb_convert_encoding($t, $from, "UTF-8");
这一步的时候并不返回?,而是返回2个字节的字符串,只是此字符串不再gb2312或big5范围内,是0x83,0x07
*/
$out .= $t;
}
}
fclose($fp);
return $out;
}