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;
}
$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;
}