Unicode是Unicode.org制定的編碼標准,目前得到了絕大部分操作系統和編程語言的支持。Unicode.org官方對Unicode的定義是:Unicode provides a unique number for every character。可見,Unicode所做的是為每個字符定義了一個相應的數字表示。比如,“a“的Unicode值是0x0061,“一”的Unicde值是0x4E00,這是最簡單的情況,每個字符用2個字節表示。
Unicode.org定義了百萬個以上的字符,如果將所有的字符用統一的格式表示,需要的是4個字節。“a“的Unicode表示就會變成0x00000061,而“一“的Unicode值是0x00004E00。實際上,這就是UTF32,Linux操作系統上所使用的Unicode方案。
但是,仔細分析可以發現,其實絕大部分字符只使用2個字節就可以表示了。英文的Unicode范圍是0x0000-0x007F,中文的Unicode范圍是0x4E00-0x9F**,真正需要擴展到4個字節來表示的字符少之又少,所以有些系統直接使用2個字節來表示Unicode。比如Windows系統上,Unicode就是兩個字節的。對於那些需要4個字節才能表示的字符,使用一種代理的手法來擴展(其實就是在低兩個字節上做一個標記,表示這是一個代理,需要連接上隨后的兩個字節,才能組成一個字符)。這樣的好處是大量的節約了存取空間,也提高了處理的速度。這種Unicode表示方法就是UTF16。一般在Windows平台上,提到Unicode,那就是指UTF16了。
至於UTF16-LE和UTF16-BE,與計算機的CPU構架有關。LE指Little Endian,而BE指Big Endian。關於這方面的信息,網上有很多相關的帖子。我們一般的X86系統都是Little Endian的,可以認為UTF16=UTF16-LE.
由於對於歐洲和北美,實際上使用的編碼范圍在0x0000-0x00FF之間,只需要一個字符就可以表示所有的字符。即使是使用UTF16來作為內存的存取方式,還是會帶來巨大的空間浪費,因此就有了UTF8的編碼方式。這是一種很靈活的編碼,對於只需要1個字節的字符,就使用一個字節,對於中日韓等原本需要兩個字節才能表示的字符,則通過一個UTF16-UTF8的算法實現相互之間的轉換(一般需要3個字節才能表示),而對於需要4個字節才能表示的字符,UTF8可以擴展到6個字節每個字符。UTF8使用的算法很有意思,大致映射關系如下:
UTF-32 UTF8
0x00000000 - 0x0000007F 0xxxxxxx
0x00000080 - 0x000007FF 110xxxxx 10xxxxxx
0x00000800 - 0x0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 - 0x001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0x00200000 - 0x03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x04000000 - 0x7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
可以發現這和IP的分址算法很是相像。
由於UTF8可以方便的轉換為UTF16和UTF32(不需要碼表,轉換算法可以在Unicode.org上找到C代碼)。而且UTF8在每個操作系統平台上的實現都是一樣的,也不存在跨平台的問題,所以UTF8成為跨平台的Unicode很好的解決方案。當然,對於中文來說,由於每個字符需要3個字節才能表示,還是有點浪費的。
出現亂碼的問題在於編碼和譯碼的格式不統一,例如編碼為window 936格式 譯碼為utf-8 通俗的說就是你將你的橡皮泥捏成一個球,然后別人問你橡皮泥
原來的形狀,你卻將他捏成一個正方體,自然認不出橡皮泥。
linux編碼譯碼均為utf-8所以不會出現亂碼情況
Win10默認編碼格式utf 16 le 編碼和譯碼的格式不統一 就像剛傳話一樣 你跟中間人說話 中間人記住了你說的話 卻告訴第三個人不一樣的話 就是這個道理。
修改方法:
首先 確認安裝了WIN10的系統中文包
然后WINDOWS - setting - time&language - Additional date,time,®ional settings - Region(Change location)
-Adnubustrative -Change system locate... -Current system locate:Chinese(Simplified,China)