重新認識unicode和utf8編碼
直到今天,準確的說是剛才,我才知道UTF-8編碼和Unicode編碼是不一樣的,是有區別的囧
他們之間是有一定的聯繫的,看看他們的卻別:
<code>UTF-8的长度是不一定的,有可能是1、2、3字节
Unicode长度一定,2个字节(USC-2)
UTF-8可以和Unicode互相转换</code>
unicode和utf8的關係
Unicode(16進位) |
UTF-8(二進位 |
0080 - 07FF
110xxxxx 10xxxxxx |
|
0800 - FFFF
1110xxxx 1007xxx 100xxx | Unicode和UTF-8字元範圍的對應,還有一個可以看出Unicode怎麼和UTF-8互相轉換: | 先說UTF-8到Unicode的轉換
UTF-8編碼的二進制和上面的3種格式進行匹配,匹配到之後去掉固定位(表格中的非x位置),然後從右到左每8位一組,不夠8位左邊不領,湊夠2個字節16 bits,這16 bits所表示的就是UTF-8對應的Unicode編碼,看看下面幾個例子: |
上面圖片中的文字編碼格式為UTF-8,可以用WinHex看到其16進製表示 |
<code>字符 => UTF-8 => UTF-8二进制=> 去掉固定位置凑够16位的二进制 => 16进制
汉 => E6B189 => 11100110 10110001 10001001 => 01101100 01001001 => 6C49
汉 => E5AD97 => 11100101 10101101 10010111 => 01011011 01010111 => 5B57
#下面是在chrome命令行下面运行的结果
'\u6C49'
"汉"
'\u5B57'
"字"
#到这里的话,从UTF-8转换到Unicode已经是一件非常容易的事了,看看转换的伪代码
读取一个字节,11100110
判断该UTF-8字符的格式,属于第三种,3个字节
继续读取2个字节得到 11100101 10101101 10010111
按照格式去掉固定位 1011011 01010111
不够16位,左边补零 01011011 01010111 => 5B57</code>
再看看從Unicode到UTF-8的轉換
<code>5B57
获取5B57所在的Unicode范围,0800 <= 5B57 <= FFFF,得知5B57的UTF-8有三个字节,形式为1110xxxx 10xxxxxx 10xxxxxx
获取5B57的二进制编码 101101101010111
用上一步骤的二进制编码从右至左拼接UTF-8编码 11100101 10101101 10010111 </code>
說說問題
再說說今天這個問題的起因,從前端輸入很多單詞,UTF-8格式每個詞最多30個字節,因此會在前端和後台分別做驗證,javascript用的是Unicode編碼,後端程式用的是UTF-8編碼,現在的解決方法是這樣
前端
<code>function utf8_bytes(str)
{
var len = 0, unicode;
for(var i = 0; i < str.length; i++)
{
unicode = str.charCodeAt(i);
if(unicode < 0x0080) {
++len;
} else if(unicode < 0x0800) {
len += 2;
} else if(unicode <= 0xFFFF) {
len += 3;
}else {
throw "characters must be USC-2!!"
}
}
return len;
}
#例子
utf8_bytes('asdasdas')
8
utf8_bytes('yrt燕睿涛')
12</code>
後台
<code>#对于GBK字符串
$len = ceil(strlen(bin2hex(iconv('GBK', 'UTF-8', $word)))/2);
#对于UTF8字符串
$len = ceil(strlen(bin2hex($word))/2);</code>
5/21/2015 8:21:53 PM
5/21/2015 8:21:53 PM
本文版權歸作者。 .com)所有,未經作者本人同意禁止任何形式的轉載,轉載文章之後必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利。
以上就介紹了重新認識unicode和utf8編碼,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。