2007年12月05日 星期三 下午 04:14
keywords:substr,substr utf-8 gbk gb2312 编码
STEP 1:
utf-8是变长的unicode编码。
以下是unicode和utf8对应关系
U-00000000 - U-0000007F: 0xxxxxxx [1 byte]
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx [2 byte]
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx [3 byte]
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx [4 btye]
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx [5 byte]
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx [6 byte]
可以看出utf-8编码的数据其byte可以分为3类:0xxxxxxx,10xxxxxx和1110xxxx(再大的也归这类,很少使用);
A类 字节值小于127(--0x80),一个字节即表示一个字,例如:数字以及大小写字母;
B类 字节值在128(0x80)和192(0xC0)之间的。该类字节只有后6位有效,不能单独存在,必须和前面字节连起来才能表示一个完整的字符,处理不当就产生乱码。
C类 字节值大于192(0xC0++)的。该类字节如果小于224(0xE0,也就是11000000-11011111,定小于1110xxxx)那么它应和下一个字节(B类)后6位连起来才能用。若小于240(0xF0,也就是1110xxxx)则需和后两个字节连用。以此类推。
UTF与unicode的关系:
Unicode是一个字符集, 可以看作为内码.而UTF 是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题, 并带来一些优点.
STEP 2: 汉字编码规范:
BIG5=繁体中文
GB2312=ASCII+常用汉字+符号
GBK=GB2312+不常用字(含BIG5繁体汉字)+图形符号
GB18030=GBK+Ext-A+藏、蒙、维吾尔等文字
向上兼容,中文Windows的缺省内码还是GBK,但是Unicode只与ASCII兼容(ISO-8859-1),与GBK码不兼容,需要根据编码表做转换。
所以,对于汉字的GBK编码是这样表示的:把一个汉字用两个字节来表示,其首字节对应0x81-0xFE(即129-224),尾字节对应除掉 (0x7F)的0x40-oxFE(即64-126和128-224)。汉字的GBK编码首字节的起始编码0x81,其二进制即为0000 1000 0000 0000,可见若一个字符的二进制逻辑与0x81之后为0时,该字符一定小于0x81,此时该字符必定不是汉字,反之,该字符应该是一个汉字的首字节。
下面是网上找到的一个中英文混合字符串的截取的常用代码:
function gb_substr($str, $start, $len)
{
$s = '';
$j = 0;
for ($i=0; $i if (ord($str[$i]) & 0x81 != 0) { //或ord($str[$i]) > '0x80'
$t = $str[$i].$str[$i+1];
if (($i >= $start) && ($i+1 < $start+$len)) $s.= $t;
$i++;
} else {
$t = $str[$i];
if (($i >= $start) && ($i < $start+$len)) $s.= $t;
}
if ($i >= $start+$len) break;
}
return $s;
}
STEP 3:utf-8编码的字串截取函数实现
PHP中没有函数可用,substr()力不从心,又因为UTF-8分别有1,2,3字节编码,中日韩文都是3字节编码,处理时根据字符编码中首字节大小区分字节数量。
下面是我的博客中用到的处理函数:
function substr_cn($str,$start=0,$len)
{
$strlen=strlen($str);
for($i=0;$i<$strlen;$i++)
{
if($i>=$start&&$i<($start+$len))
{
if(ord(substr($str,$i,1))>'0xE0')
{
$tmpstr.=substr($str,$i,3); //utf-8 code
$i=$i+2;
}
else
$tmpstr.=substr($str,$i,1);
}
}
if(strlen($tmpstr)>$len)
{
$len--;
return substr_cn($str,$start,$len);
}
return $tmpstr;
}
STEP 4:相关的一个完整函数供研究使用:
function cut_str($sourcestr,$cutlength)
{
$returnstr='';
$i=0;
$n=0;
$str_length=strlen($sourcestr);//字符串的字节数
while (($n<$cutlength) and ($i<=$str_length))
{
$temp_str=substr($sourcestr,$i,1);
$ascnum=Ord($temp_str);//得到字符串中第$i位字符的ascii码
if ($ascnum>=224) //如果ASCII位高与224,
{
$returnstr=$returnstr.substr($sourcestr,$i,3); //根据UTF-8编码规范,将3个连续的字符计为单个字符
$i=$i+3; //实际Byte计为3
$n++; //字串长度计1
}
elseif ($ascnum>=192) //如果ASCII位高与192,
{
$returnstr=$returnstr.substr($sourcestr,$i,2); //根据UTF-8编码规范,将2个连续的字符计为单个字符
$i=$i+2; //实际Byte计为2
$n++; //字串长度计1
}
elseif ($ascnum>=65 && $ascnum<=90) //如果是大写字母,
{
$returnstr=$returnstr.substr($sourcestr,$i,1);
$i=$i+1; //实际的Byte数仍计1个
$n++; //但考虑整体美观,大写字母计成一个高位字符
}
else //其他情况下,包括小写字母和半角标点符号,
{
$returnstr=$returnstr.substr($sourcestr,$i,1);
$i=$i+1; //实际的Byte数计1个
$n=$n+0.5; //小写字母和半角标点等与半个高位字符宽...
}
}
if ($str_length>$cutlength){
$returnstr = $returnstr . "...";//超过长度时在尾处加上省略号
}
return $returnstr;
}
keywords:substr,substr utf-8 gbk gb2312 编码
STEP 1:
utf-8是变长的unicode编码。
以下是unicode和utf8对应关系
U-00000000 - U-0000007F: 0xxxxxxx [1 byte]
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx [2 byte]
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx [3 byte]
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx [4 btye]
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx [5 byte]
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx [6 byte]
可以看出utf-8编码的数据其byte可以分为3类:0xxxxxxx,10xxxxxx和1110xxxx(再大的也归这类,很少使用);
A类 字节值小于127(--0x80),一个字节即表示一个字,例如:数字以及大小写字母;
B类 字节值在128(0x80)和192(0xC0)之间的。该类字节只有后6位有效,不能单独存在,必须和前面字节连起来才能表示一个完整的字符,处理不当就产生乱码。
C类 字节值大于192(0xC0++)的。该类字节如果小于224(0xE0,也就是11000000-11011111,定小于1110xxxx)那么它应和下一个字节(B类)后6位连起来才能用。若小于240(0xF0,也就是1110xxxx)则需和后两个字节连用。以此类推。
UTF与unicode的关系:
Unicode是一个字符集, 可以看作为内码.而UTF 是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题, 并带来一些优点.
STEP 2: 汉字编码规范:
BIG5=繁体中文
GB2312=ASCII+常用汉字+符号
GBK=GB2312+不常用字(含BIG5繁体汉字)+图形符号
GB18030=GBK+Ext-A+藏、蒙、维吾尔等文字
向上兼容,中文Windows的缺省内码还是GBK,但是Unicode只与ASCII兼容(ISO-8859-1),与GBK码不兼容,需要根据编码表做转换。
所以,对于汉字的GBK编码是这样表示的:把一个汉字用两个字节来表示,其首字节对应0x81-0xFE(即129-224),尾字节对应除掉 (0x7F)的0x40-oxFE(即64-126和128-224)。汉字的GBK编码首字节的起始编码0x81,其二进制即为0000 1000 0000 0000,可见若一个字符的二进制逻辑与0x81之后为0时,该字符一定小于0x81,此时该字符必定不是汉字,反之,该字符应该是一个汉字的首字节。
下面是网上找到的一个中英文混合字符串的截取的常用代码:
function gb_substr($str, $start, $len)
{
$s = '';
$j = 0;
for ($i=0; $i
$t = $str[$i].$str[$i+1];
if (($i >= $start) && ($i+1 < $start+$len)) $s.= $t;
$i++;
} else {
$t = $str[$i];
if (($i >= $start) && ($i < $start+$len)) $s.= $t;
}
if ($i >= $start+$len) break;
}
return $s;
}
STEP 3:utf-8编码的字串截取函数实现
PHP中没有函数可用,substr()力不从心,又因为UTF-8分别有1,2,3字节编码,中日韩文都是3字节编码,处理时根据字符编码中首字节大小区分字节数量。
下面是我的博客中用到的处理函数:
function substr_cn($str,$start=0,$len)
{
$strlen=strlen($str);
for($i=0;$i<$strlen;$i++)
{
if($i>=$start&&$i<($start+$len))
{
if(ord(substr($str,$i,1))>'0xE0')
{
$tmpstr.=substr($str,$i,3); //utf-8 code
$i=$i+2;
}
else
$tmpstr.=substr($str,$i,1);
}
}
if(strlen($tmpstr)>$len)
{
$len--;
return substr_cn($str,$start,$len);
}
return $tmpstr;
}
STEP 4:相关的一个完整函数供研究使用:
function cut_str($sourcestr,$cutlength)
{
$returnstr='';
$i=0;
$n=0;
$str_length=strlen($sourcestr);//字符串的字节数
while (($n<$cutlength) and ($i<=$str_length))
{
$temp_str=substr($sourcestr,$i,1);
$ascnum=Ord($temp_str);//得到字符串中第$i位字符的ascii码
if ($ascnum>=224) //如果ASCII位高与224,
{
$returnstr=$returnstr.substr($sourcestr,$i,3); //根据UTF-8编码规范,将3个连续的字符计为单个字符
$i=$i+3; //实际Byte计为3
$n++; //字串长度计1
}
elseif ($ascnum>=192) //如果ASCII位高与192,
{
$returnstr=$returnstr.substr($sourcestr,$i,2); //根据UTF-8编码规范,将2个连续的字符计为单个字符
$i=$i+2; //实际Byte计为2
$n++; //字串长度计1
}
elseif ($ascnum>=65 && $ascnum<=90) //如果是大写字母,
{
$returnstr=$returnstr.substr($sourcestr,$i,1);
$i=$i+1; //实际的Byte数仍计1个
$n++; //但考虑整体美观,大写字母计成一个高位字符
}
else //其他情况下,包括小写字母和半角标点符号,
{
$returnstr=$returnstr.substr($sourcestr,$i,1);
$i=$i+1; //实际的Byte数计1个
$n=$n+0.5; //小写字母和半角标点等与半个高位字符宽...
}
}
if ($str_length>$cutlength){
$returnstr = $returnstr . "...";//超过长度时在尾处加上省略号
}
return $returnstr;
}
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1869/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
评论列表