全角字符与半角字符的互相转化

1.类的实现


/**
 * 概念
 * 全角字符unicode编码从65281~65374 (十六进制 0xFF01 ~ 0xFF5E)
 * 半角字符unicode编码从33~126 (十六进制 0x21~ 0x7E)
 * 空格比较特殊,全角为 12288(0x3000),半角为 32 (0x20)
 * 而且除空格外,全角/半角按unicode编码排序在顺序上是对应的
 * 所以可以直接通过用+-法来处理非空格数据,对空格单独处理
 *
 * 实现思路
 * 1. 找到目标unicode的字符,可以使用正则表达式解决
 * 2. 修改unicode编码
 *
 * @url https://www.cnblogs.com/365star/p/5213963.html
 */

class SbcDbcFormat
{
    /**
     * 将unicode转换成字符
     * 
     * @param int $unicode
     * @return string UTF-8字符
     **/
    public function unicode2Char($unicode)
    {
        if($unicode < 128)
            return chr($unicode);
        if($unicode < 2048)
            return chr(($unicode >> 6) + 192) . chr(($unicode & 63) + 128);
        if($unicode < 65536)
            return chr(($unicode >> 12) + 224) . chr((($unicode >> 6) & 63) + 128) . chr(($unicode & 63) + 128);
        if($unicode < 2097152)
            return chr(($unicode >> 18) + 240) . chr((($unicode >> 12) & 63) + 128) . chr((($unicode >> 6) & 63) + 128) . chr(($unicode & 63) + 128);
        return false;
    }

    /**
     * 将字符转换成unicode
     * 
     * @param string $char 必须是UTF-8字符
     * @return int
     **/
    public function char2Unicode($char)
    {
        switch (strlen($char))
        {
            case 1 :
                return ord($char);
            case 2 :
                return (ord($char{1}) & 63) | ((ord($char{0}) & 31) << 6);
            case 3 :
                return (ord($char{2}) & 63) | ((ord($char{1}) & 63) << 6) | ((ord($char{0}) & 15) << 12);
            case 4 : return (ord($char{3}) & 63) | ((ord($char{2}) & 63) << 6) | ((ord($char{1}) & 63) << 12) | ((ord($char{0}) & 7)  << 18);
            default :
                trigger_error('Character is not UTF-8!', E_USER_WARNING);
                return false;
        }
    }

    /**
     * 全角转半角
     * 
     * @param string $str
     * @return string
     **/
    public function sbc2Dbc($str)
    {
        return preg_replace_callback(
            '/[\x{3000}\x{ff01}-\x{ff5f}]/u',
            function($matches){
                $unicode=$this->char2Unicode($matches[0]);
                if($unicode == 0x3000){
                    return " ";
                }
                $code = $unicode-0xfee0;
                if($code  > 256){
                    return $this->unicode2Char($code);
                }else{
                    return chr($code);
                }
            },
            $str);
    }

    /**
     * 半角转全角
     * 
     * @param string $str
     * @return string
     **/
    public function dbc2Sbc($str)
    {
        return preg_replace_callback(
            // 半角字符
            '/[\x{0020}\x{0020}-\x{7e}]/u',
            // 编码转换
            // 0x0020是空格,特殊处理,其他半角字符编码+0xfee0即可以转为全角
            function ($matches){
                $unicode=$this->char2Unicode($matches[0]);
                if($unicode == 0x0020){
                    return $this->unicode2Char(0x3000);
                }

                $code=$unicode+0xfee0;
                if($code >256){
                    return $this->unicode2Char($code);

                }else{
                    return chr($code);
                }
            },
            $str);
    }
}

2.使用示例

$str = 'xxxxxxx';
$sbcDbcFormat = new SbcDbcFormat();
$str = $sbcDbcFormat->sbc2Dbc($str);

你可能感兴趣的:(PHP)