Javascript的坑之utf8編碼



1.原由

使用javascript開發的時候發現,在部分第三方庫中,對emoji的字符串進行UTF8編碼出錯。

調查發現,javascript的string編碼為UTF16(出處),而我們大部分時候使用的是UTF8。由於UTF16的設計,在大部分情況下編碼javascript的字符串到UTF8都是沒問題的。

出問題的地方在剩下的那部分,我們先看UTF8和UTF16的異同。

 

2.UTF8 and UTF16

wiki上關於UTF8UTF16的資料已經很詳細了。

首先要理解的是無論是UTF8還是UTF16都是Unicode的一種形式。而Unicode其實就是一個字符表,范圍為0~0x10FFFF。其間的每個數字是一個code point,所有的這些code point組成了Unicode的code space.

而UTF8和UTF16則是code point的不同編碼方式。

UTF8使用變長的8-bit code units來表示code point。具體編碼方式可以看wiki百科的說明。

UTF16的code units則是16-bit.並且當code point在0~0xFFFF的范圍內時,UTF16的code units在數字上等於code point的值。在U+10000到U+10FFFF范圍時則需要進行編碼。

 

3.目標

我們的目標是將javascript的字符串進行UTF8編碼,而javascript字符串的編碼方式為UTF16,因此我們的目的就是將UTF16轉換為UTF8.

轉換的過程也很簡單,UTF16->code points->UTF8

 

4.問題所在

上面我們可以看到,對於javascript的字符串,也就是UTF16編碼的字符串,由於當code point的值在0~0xFFFF之間時, UTF16的編碼值和code point上數值相同,並且生活中大部分情況下我們只會用到這個范圍內的值,因此部分第三方庫在進行UTF8編碼時,直接省略了之前的UTF16->code points這一步。

也就是說這個范圍內的UTF16進行UTF8編碼的時候可以直接調用javascript中String.charCodeAt()方法來獲取每個UTF16字符code point的值,然后再根據UTF8編碼的規則進行轉換。

然而String.charCodeAt()方法獲取的值並不是和Unicode的code points完全相等,因此就會出錯。

 

5.解決方法

如果是使用nodejs開發的話,可以直接使用utf8.js這個庫。

而在瀏覽器中則可根據wiki上的編碼解碼規則,使用String.charCodeAt()方法獲得UTF16的值,然后解碼為Unicode的code point,之后編碼code point到UTF8即可。是比較簡單的,而且可以借鑒utf8.js的寫法。

不過因為不同第三方庫對字符串進行UTF8編碼的情景不同,因此可能需要針對單獨的庫進行相應的調整,只要掌握了UTF8和UTF16的編碼解碼過程並不難。然而還是要鄙視一下這種自己造輪子結果漏氣的行為。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM