您当前的位置:首页 > 分类 > 技术资讯 > PHP > 正文

php字符长度,宽度计算及应用

发布时间:2016-11-15 14:41:33      来源:51推一把
【摘要】mb_strwidth 返回string类型str的宽度,多字节字符通常是单字节字符的两倍宽度。
//测试时文件的编码方式要是UTF8  
$str=中文a字1符;  //4个汉字,1个字母,1个数字

echo strlen($str).<br>;//14  

字符数
echo mb_strlen($str).<br>;//14
echo mb_strlen($str,utf8).<br>;//6  
echo mb_strlen($str,gbk).<br>;//8  
echo mb_strlen($str,gb2312).<br>;//10

字节数
echo mb_strwidth($str).<br>;//14         
echo mb_strwidth($str,utf8).<br>;//10  
echo mb_strwidth($str,gbk).<br>;//11
echo mb_strwidth($str,gb2312).<br>;//12

结果分析:
在strlen计算时,对待一个UTF8的中文字符是3个长度,所以“中文a字1符”长度是3*4+2=14,
在mb_strlen计算时,选定内码为UTF8,则会将一个中文字符当作长度1来计算,所以“中文a字1符”长度是6.

PHP内置的字符串长度函数strlen无法正确处理中文字符串,它得到的只是字符串所占的字节数。
对于GB2312的中文编码,strlen得到的值是汉字个数的2倍,
而对于UTF-8编码的中文,就是3倍的差异了(在 UTF-8编码下,一个汉字占3个字节)。

判断中文和编码有关 gbk是双字节,utf8是三字节,可以根据 中文的范围来判断

编码范围
1. GBK (GB2312/GB18030)
x00-xff GBK双字节编码范围
x20-x7f ASCII
xa1-xff 中文
x80-xff 中文
2. UTF-8 (Unicode)
u4e00-u9fa5 (中文)
x3130-x318F (韩文
xAC00-xD7A3 (韩文)
u0800-u4e00 (日文)
ps: 韩文是大于[u9fa5]的字符

mb_strwidth()利用宽度,一个汉字占2个字母宽度
/**
 * utf8 编码格式
 * 1个中文占用3个字节
 * 我们希望的是1个中文占用2个字节,
 * 因为从宽度上看2个英文字母占用的位置相当于1个中文
 */

//宽度截取字符串
int mb_strwidth ($str,$encoding)
string mb_strimwidth ($str ,$start ,$width ,$encoding)

中文符号占1个宽度
如果对于全中文没有问题但如果中间有符号了就有问题了,如我使用mb_strimwidth,mb_strwidth,后发现如果标题中存在“”符号的时候,PHP mb_strwidth会将该符号认为是1个宽度,这个不是中文的双引号嘛,照理说肯定是宽字节的,长度应该是2个宽度,后查询“”unicode分别为u201C和u201D,不在中文字符的范围中,再查询unicode.org 的码表,发现u2000-u206F是通用符号的范围,此范围中的字符虽然都是宽字符的形式,但是PHP 的mb_函数却认为是1个宽度。

#使用到循环遍历算字符编码取字符位数

function truncString($str, $length)  
{  
    $countLen=0;  
    for($i=0;$i<mb_strlen($str);$i++)  
    {  
    $countLen+=amb_strwidth(mb_substr($str,$i,1));  
    if($countLen>$length)  
    return mb_substr($str,0,$i);  
     }  
     return $str;  
}  
function amb_strwidth($str_width)  
{  
    $count=0;  
    for($i=0;$i<mb_strlen($str_width);$i++)  
    {  
    //if(mb_substr($str_width,$i,1)=="\xE2\x80\x9C"||mb_substr($str_width,$i,1)==\xE2\x80\x9D)  
    //如果遇到u2000-u206F内的字符则将计数器加2  
    if(preg_match("/[\x{2000}-\x{206F}]/u",mb_substr($str_width,$i,1)))  
        $count+=2;  
    else  
        $count+=mb_strwidth(mb_substr($str_width,$i,1));  
    }  
    return $count;  
}