目錄
- 了解字符編碼
- Unicode與UTF-8近忙,UTF-16之間的關(guān)系
- 字符編碼常見問題
- 相關(guān)資料鏈接
1. 了解字符編碼
字符編碼,即其字面意智润,就是每一個字符都對應(yīng)一個編碼(根據(jù)規(guī)格不同及舍,最終得到的編碼結(jié)果也不同)。我們在日常使用中窟绷,經(jīng)常接觸到的字符編碼有以下三種:ASCII,ANSI兼蜈,Unicode攘残。
ASCII編碼: 是這三種編碼中最原始的編碼方式,即采用一個字節(jié)(8位二進制位)對字符進行編碼为狸。低7位二進制位進行編碼歼郭,第8位通常為0,十進制可以表示為0128辐棒,十六進制為0x000x8F病曾。因此ASCII可以標識128個常用字符牍蜂,其中有 96 個可打印字符,包括常用的字母泰涂、數(shù)字鲫竞、標點符號等,另外還有 32 個控制字符负敏。
ANSI編碼: 是各個國家對ASCII的擴充贡茅,它根據(jù)用戶所使用的系統(tǒng)的不同而不同,如在中文操作系統(tǒng)下其做,字符編碼為GB2312編碼顶考,而在日文操作系統(tǒng)下,則是ANSI 編碼代表 JIS 編碼等妖泄。
因此也會出現(xiàn)一個問題:如果在中文系統(tǒng)中保存為ANSI編碼驹沿,那么在日文操作系統(tǒng)中,直接打開就會出現(xiàn)亂碼蹈胡,因為此時日文系統(tǒng)的ANSI編碼代表的是JIS編碼渊季,而保存的編碼格式是GB2312編碼。Unicode編碼: 上述中的ANSI編碼方式得到的字符編碼罚渐,由于其編碼規(guī)范都具有區(qū)域性却汉,因此,可能會出現(xiàn)荷并,同一個字符使用不同編碼方式時合砂,出現(xiàn)不同編碼值;同一個編碼值在不同的編碼方式中源织,代表的字符也不同翩伪。因此Unicode編碼出現(xiàn)了,它統(tǒng)一了字符編碼規(guī)范谈息,使得字符和編碼值實現(xiàn)一一對應(yīng)的關(guān)系豹障。
2. Unicode與UTF-8噪径,UTF-16之間的關(guān)系
UTF-8,UTF-16出現(xiàn)的原因
根據(jù)上面提到的Unicode已經(jīng)滿足了人們的同意編碼的要求烙懦,但是為什么還會出現(xiàn)UTF-8和UTF-16這兩種編碼方式呢吕世?
主要原因:直接使用Unicode編碼的效率不高缭裆,比如UCS-4(Unicode的標準之一)規(guī)定用4個字節(jié)存儲一個符號市咆,那么每個英文字母前都必然有三個字節(jié)是0疼阔,這對存儲和傳輸來說都很耗資源。
因此嗅骄,UTF-8和UTF-16對于Unicode來說,就是提供了額外的編碼方式饼疙。用特定的編碼規(guī)則來解決Unicode編碼的效率問題溺森。
UTF-8慕爬,UTF-16如何解決效率問題
由上圖可知,一個英文字符占用1個字節(jié)屏积,一個中文字符占用3個字節(jié)炊林,一個表情(特殊字符)占用四個字節(jié)。
可以看出,UTF-8根據(jù)不同的字符類型,采用不同的字節(jié)進行存儲忘晤,相對有上面提到的UCS-4來說,對任意字符都采用4字節(jié)存儲缩幸,會更加的高效。
對于UTF-16編碼难咕,在U+0000 - U+FFFF范圍類跨算,都固定是使用2個字節(jié)進行存儲氧猬,因此不管是中文還是因為字符倔矾,都是用兩個字節(jié)。
UTF-8,UTF-16轉(zhuǎn)換規(guī)則
UTF-8
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+10FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
UTF-16
U+0000 - U+FFFF xxxxxxxx xxxxxxxx
U+10000 - U+10FFFF 110110xx xxxxxxxx 110111xx xxxxxxxx
如,‘我’的Unicode編碼為6211瘸爽,如果采用UTF-8編碼柑潦,該編碼落在U+ 0800 ~ U+ FFFF范圍內(nèi)峻凫,因此其轉(zhuǎn)換方式為
UTF-8渗鬼,UTF-16使用場景
- UTF-8是目前互聯(lián)網(wǎng)上最常用的一種編碼格式。
- UTF-8的優(yōu)勢在于荧琼,其英文字符只需要1個字節(jié)來表示譬胎,但是中文字符卻需要3個字節(jié)。
- UTF-16的優(yōu)勢在于命锄,其中文字符只需要2個字節(jié)來表示堰乔,但是英文字符也需要2個字節(jié)。
因此脐恩,如果文本中镐侯,主要是中文字符,則使用UTF-16驶冒;主要使用英文字符苟翻,則使用UTF-8搭伤。當(dāng)然也要適當(dāng)考慮第一條,即通用性袜瞬。
3. 字符編碼常見問題
亂碼問題
正常情況下,主要由于文本的編碼方面出現(xiàn)問題:
使用ANSI編碼進行存儲
如上面提到的身堡,在不同語言的操作系統(tǒng)中邓尤,打開使用ANSI編碼保存的文本時,就會出現(xiàn)保存和打開時的編碼方式不一致贴谎,如果在中文系統(tǒng)中保存為ANSI編碼汞扎,那么在日文操作系統(tǒng)中,直接打開就會出現(xiàn)亂碼擅这,因為此時日文系統(tǒng)的ANSI編碼代表的是JIS編碼澈魄,而保存的編碼格式是GB2312編碼。本地編輯器設(shè)置打開的編碼方式不正確
每個文本編輯器中都可以設(shè)置文本的編碼格式仲翎。如sublime中文本文件默認的編碼格式即為‘utf-8’痹扇,如果文本保存的格式為GBK,使用sublime打開時溯香,默認使用uft-8格式鲫构,這就導(dǎo)致中文出現(xiàn)亂碼。
在sublime中玫坛,默認不會顯示文本的字符編碼结笨,需要手動修改配置文件,菜單Perference → Settings – User湿镀,修改用戶配置炕吸,覆蓋默認配置。
windows中文件文件編輯器的問題
千萬不要使用Windows自帶的記事本編輯任何文本文件勉痴。原因是Microsoft開發(fā)記事本的團隊使用了一個非常弱智的行為來保存UTF-8編碼的文件赫模,他們自作聰明地在 每個文件開頭添加了0xefbbbf(十六進制)的字符,你會遇到很多不可思議的問題蚀腿,比如嘴瓤,網(wǎng)頁第一行可能會顯示一個“?”,明明正確的程序一編譯就報語法錯誤莉钙,等等廓脆,都是由記事本的弱智行為帶來的。建議你下載Notepad++代替記事本磁玉,不但功能強大停忿,而且免費!記得把Notepad++的默認編碼設(shè)置為UTF-8 without BOM即可蚊伞。
網(wǎng)絡(luò)傳輸中文件字符編碼問題
下面針對一個最簡單的HTML文件進行講解:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="gbk">
<title>Document</title>
</head>
<body>
welcome to Beijing! 歡迎來到北京席赂!??????
</body>
</html>
http.createServer(function(req, res) {
let content = fs.readFileSync('./test.html', 'utf-8');
res.setHeader('Content-Type', 'text/html;')
res.write(content);
res.end();
})
此時吮铭,如果我們使用utf-8編碼保存HTML文件,然后我們在服務(wù)器中颅停,使用utf-8編碼形式讀取文件谓晌。但是此時,我們訪問服務(wù)器癞揉,獲取的html頁面卻得到了亂碼纸肉。
這是為什么呢?
仔細觀察喊熟,頁面頭部的meta標簽柏肪。
<meta charset="gbk">
這個標簽,告訴瀏覽器芥牌,這個html字符編碼是gbk編碼烦味,因此瀏覽器就會使用gbk編碼的方式識別字符,因此會出現(xiàn)亂碼壁拉。
但是谬俄,如果你在響應(yīng)頭中,設(shè)置charset=utf-8'弃理,則可以解決這個問題凤瘦。
res.setHeader('Content-Type', 'text/html;charset=utf-8')
此時,瀏覽器就會忽略<meta charset="gbk">標簽案铺,使用響應(yīng)頭中標識的字符集蔬芥,瀏覽器頁面也會正常展示。