重新認識unicode和utf8編碼
直到今天,準確的說是剛才,我才知道UTF-8編碼和Unicode編碼是不一樣的,是有區別的囧
他們之間是有一定的聯絡的,看看他們的卻別:
UTF-8的長度是不一定的,有可能是1、2、3位元組Unicode長度一定,2個位元組(USC-2)UTF-8可以和Unicode互相轉換
unicode和utf8的關係
| Unicode(16進位) |
UTF-8(二進位) |
| 0000 - 007F |
0xxxxxxx |
| 0080 - 07FF |
110xxxxx 10xxxxxx |
| 0800 - FFFF |
1110xxxx 10xxxxxx 10xxxxxx |
上面的表格有2個意思,第一個顯而易見就是說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進位表示
字元=> UTF-8 => UTF-8二進位=> 去掉固定位置湊夠16位的二進位 => 16進位漢 => E6B189 => 11100110 10110001 10001001=> 01101100 01001001 => 6C49漢 => E5AD97 => 11100101 10101101 10010111=> 0101101101010111 => 5B57#下面是在chrome命令列下面啟動並執行結果'\u6C49'"漢"'\u5B57'"字"#到這裡的話,從UTF-8轉換到Unicode已經是一件非常容易的事了,看看轉換的虛擬碼讀取一個位元組,11100110判斷該UTF-8字元的格式,屬於第三種,3個位元組繼續讀取2個位元組得到 11100101 10101101 10010111按照格式去掉固定位 1011011 01010111不夠16位,左邊補零 01011011 01010111 => 5B57
再看看從Unicode到UTF-8的轉換
5B57擷取5B57所在的Unicode範圍,0800 <= 5B57 <= FFFF,得知5B57的UTF-8有三個位元組,形式為1110xxxx 10xxxxxx 10xxxxxx擷取5B57的二進位編碼 101101101010111用上一步驟的二進位編碼從右至左拼接UTF-8編碼 11100101 10101101 10010111
說說問題
再說說今天這個問題的起因,從前端輸入很多單詞,UTF-8格式每個詞最多30個位元組,因此會在前端和後台分別做驗證,javascript用的是Unicode編碼,後端程式用的是UTF-8編碼,現在的解決辦法是這樣
前端
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')8utf8_bytes('yrt燕睿濤')12
後台
#對於GBK字串$len = ceil(strlen(bin2hex(iconv('GBK', 'UTF-8', $word)))/2);#對於UTF8字串$len = ceil(strlen(bin2hex($word))/2);
5/21/2015 8:21:53 PM
本文著作權歸作者iforever(luluyrt@163.com)所有,未經作者本人同意禁止任何形式的轉載,轉載文章之後必須在文章頁面明顯位置給出作者和原文串連,否則保留追究法律責任的權利。
以上就介紹了重新認識unicode和utf8編碼,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。