这是原来的代码,本身就不错

PHP 截取中文字符串(支持多种编码)

通过PHP 截取中文字符串(支持多种编码) - 开源中国社区.

我改的增加了一些计算和是否添加尾缀的判断,所以性能上会略差,欢迎吐槽

/**
 * 字符串截取,支持中文和其他编码
 *
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断字符串后缀
 * @return string
 */
function substr_ext($str, $start=0, $length, $charset="utf-8", $suffix="")
{
    //处理尾缀,由于该参数比较特殊,只能分开处理
    if(function_exists("mb_strlen"))
        if (((mb_strlen($str)-$start)<$length))
            $suffix = '';   //如果字符串没超出长度不添加尾缀
    if(function_exists("mb_substr")){
        return mb_substr($str, $start, $length, $charset).$suffix;
    }
    //我们的服务器支持mb_substr 所以直接注释掉下面的内容
    elseif(function_exists('iconv_substr')){
        if (function_exists('iconv_strlen'))
            if (((iconv_strlen($str)-$start)<$length))
                $suffix = '';   //如果字符串没超出长度不添加尾缀
        return iconv_substr($str,$start,$length,$charset).$suffix;
    }
    //不支持mb_substr 或者 iconv_substr的服务器运行以下低效率语句
    $length +=$length; //接下来的过程中一个中文要占2个字符所以length加倍
    //$reAscii = "/[\x01-\x7f]|"; 这句暂时没有用。可以删掉
    $re['utf-8']  = "[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
    $re['gb2312'] = "[\xb0-\xf7][\xa0-\xfe]/";
    $re['gbk']    = "[\x81-\xfe][\x40-\xfe]/";
    $re['big5']   = "[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
    //preg_match_all($reAscii.$re[$charset], $str, $match);
    $str = mb_convert_encoding($str, 'utf-8'); //先转成utf-8才能进行之后的操作
    $newStr = StringToArray($str); //字面意思 ,将字符串分离为数组
    $strLen = 0;
    $outStr = "";   
    foreach($newStr as $key => $val){   //计算长度,一个中文占2个字符
        if ($key<$start)
            continue;
        if(preg_match("/".$re[$charset],$val))
            $strLen +=2;
        else
            ++$strLen;
        if ($strLen<$length)    //如果没超长,往新的字符串里放文字
            $outStr = $outStr.$val;
    }
    if ($strLen-$start<$length)
        $suffix = "";   //如果没超出字符限制不添加尾缀
    //$slice = join("",array_slice($match[0], $start, $length));
    return $outStr.$suffix;
    
}
/**
 * 把字符串转成数组,支持汉字,只能是utf-8格式的
 * @param $str
 * @return array
 */
function StringToArray($str)
{
    $result = array();
    $len = strlen($str);
    $i = 0;
    while($i < $len){
        $chr = ord($str[$i]);
        if($chr == 9 || $chr == 10 || (32 <= $chr && $chr <= 126)) {
            $result[] = substr($str,$i,1);
            $i +=1;
        }elseif(192 <= $chr && $chr <= 223){
            $result[] = substr($str,$i,2);
            $i +=2;
        }elseif(224 <= $chr && $chr <= 239){
            $result[] = substr($str,$i,3);
            $i +=3;
        }elseif(240 <= $chr && $chr <= 247){
            $result[] = substr($str,$i,4);
            $i +=4;
        }elseif(248 <= $chr && $chr <= 251){
            $result[] = substr($str,$i,5);
            $i +=5;
        }elseif(252 <= $chr && $chr <= 253){
            $result[] = substr($str,$i,6);
            $i +=6;
        }
    }
    return $result;
}

转载保留版权:http://haipz.com/blog/i/2974 - 海胖博客