unicode
首先搞清兩個概念汤徽,字符集 與 編碼
- 字符集:字符集是一張碼表桥言,它規(guī)定了文字與數(shù)字的一一對應(yīng)關(guān)系。與計算機的內(nèi)部表示沒有必然的聯(lián)系厌漂。比如ASCII字符集,它規(guī)定了0~127這128個數(shù)字與哪些字符的對應(yīng)關(guān)系斟珊。常見的字符集包括:ASCII苇倡,GB2312,unicode等。
- 編碼: 字符集是數(shù)字與字符對應(yīng)起來的方案旨椒,編碼則是在計算機與網(wǎng)絡(luò)中存儲晓褪、傳輸這些數(shù)字的方案。常見的編碼方式有utf8综慎、utf16涣仿、GBK等。
unicode(統(tǒng)一碼示惊、萬國碼好港、單一碼、標(biāo)準(zhǔn)萬國碼)是世界范圍內(nèi)通用的字符集米罚,是一種標(biāo)準(zhǔn)媚狰,它可以使電腦同時顯示世界上數(shù)十種文字。unicode編碼系統(tǒng)為表達任意語言的任意字符而設(shè)計阔拳,使用4字節(jié)的數(shù)字來表達每個字母、符號类嗤,或者表意文字糊肠。在unicode出現(xiàn)之前,世界各地都搞一套自己語音的字符集遗锣,混亂不堪货裹,于是unicode組織就挺身而出,它們的目標(biāo)是囊括世界上所有的字符精偿,同時解決歷史問題弧圆,將既有的字符編碼方案以Unicode 編碼方案來加以取代。
歷史元老中笔咽,ASCII搔预、GB2312是兼字符集與編碼方案為一身的,而unicode則是單純的字符集叶组,它有多種編碼方案的實現(xiàn)拯田,如utf8、GBK等等甩十。字符集和編碼的概念被徹底分離且模塊化的模型船庇,其實是 Unicode 時代才得到廣泛認(rèn)同的。不同的編碼方案在存儲空間上各有長處侣监,有的存英文省鸭轮,有的存中文省。
JavaScript的字符串是unicode字符串橄霉,內(nèi)部以utf-16編碼保存窃爷。
ES6中的String.prototype.codePointAt()
方法可以得到指定字符的unicode碼點。
JavaScript中不存在gbk字符串、utf8字符串這樣的東西吞鸭,但可以通過宿主環(huán)境或是第三方庫提供的轉(zhuǎn)碼方法寺董,來將js字符串轉(zhuǎn)化為其他編碼,并用某種數(shù)據(jù)結(jié)構(gòu)(如瀏覽器中的ArrayBuffer刻剥,Node中的Buffer)來保存遮咖。
node支持的編碼類型
目前有:
- ascii
- base64
- binary
- hex
- ucs2/ucs-2/utf16le/utf-16le
- utf8/utf-8
- latin1 (ISO8859-1, only in node 6.4.0+)
使用node的讀寫流時,若data是string造虏,則可以指定encoding參數(shù)御吞,以指定的編碼類型來讀寫字符串;若data是buffer漓藕,則忽略encoding參數(shù)陶珠。例如文件讀寫:
fs.writeFile('./xx.txt', '哈哈哈', 'utf8') // use string and encoding
fs.writeFile('./xx.txt', new Buffer('哈哈哈', 'utf8')) // use string
fs.readFile('./xx.txt', 'utf8', (err, data) => {...}) // data is a string
fs.readFile('./xx.txt', (err, data) => {...}) // data is a raw buffer
node中轉(zhuǎn)換字符編碼
node是不支持gbk、gb2312等上述以外編碼的享钞,如果指定encoding為它們會報錯Unknown encoding: xx
揍诽。但可以通過第三方模塊iconv-lite來轉(zhuǎn)換編碼±跏基本操作如下:
// 讀
const iconv = require('iconv-lite')
let data = fs.readFileSync('./xx.txt') // 假設(shè)txt是GB2312編碼的暑脆,data是一個buffer,存儲GB2312編碼的字符串?dāng)?shù)據(jù)
let str = iconv.decode(data, 'GB2312') // 將buffer解碼為string
// 拿到一個buffer欲將它轉(zhuǎn)為string狐肢,必須先知道它的編碼類型
// 寫
const str = '國慶節(jié)萬歲'
let b = iconv.encode(str, 'GB2312') // b是一個buffer添吗,存儲的是str的GB2312編碼的二進制
fs.writeFile('./xx.txt', b) // 將str的GB2312編碼數(shù)據(jù)寫入到文件中
Base64/hex
Base64與hex都是將二進制數(shù)據(jù)編碼成字符串的編碼方式,針對的是二進制字節(jié)而非字符串份名。
因此碟联,要獲得某個string的base64編碼時,應(yīng)該先得到string的二進制僵腺,再對二進制進行base6編碼:
// 編碼
const str = '哈哈'
let b = Buffer.from(str) // b中存的是哈哈的utf8編碼二進制
let base64Code = b.toString('base64') // '5ZOI5ZOI'
// 解碼
const code = '5ZOI5ZOI'
let str = Buffer.from('5ZOI5ZOI', 'base64') // '哈哈'