站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

聊聊Node.js Buffer中的encoding(編碼)

本篇文章帶大家了解一下Node.js Buffer中的encoding,希望對(duì)大家有所幫助!

聊聊Node.js Buffer中的encoding(編碼)

計(jì)算機(jī)最小的單位是一個(gè)位,也就是 0 和 1,在硬件上通過(guò)高低電平來(lái)對(duì)應(yīng)。但是只有一位表示的信息太少了,所以又規(guī)定了 8 個(gè)位為一個(gè)字節(jié),之后數(shù)字、字符串等各種信息都是基于字節(jié)來(lái)存儲(chǔ)的。【推薦學(xué)習(xí):《nodejs 教程》】

字符怎么存儲(chǔ)呢?就是靠編碼,不同的字符對(duì)應(yīng)不同的編碼,然后在需要渲染的時(shí)候根據(jù)對(duì)應(yīng)編碼去查字體庫(kù),然后渲染對(duì)應(yīng)字符的圖形。

字符集

字符集(charset)最早是 ASCII 碼,也就是 abc ABC 123 等 128 個(gè)字符,因?yàn)橛?jì)算機(jī)最早就是美國(guó)發(fā)明的。后來(lái)歐洲也制定了一套字符集標(biāo)準(zhǔn),叫做 ISO,后來(lái)中國(guó)也搞了一套,叫做 GBK。

國(guó)際標(biāo)準(zhǔn)化組織覺(jué)得不能這樣各自搞一套,不然同一個(gè)編碼在不同字符集里面就不同的意思,于是就提出了 unicode 編碼,把全世界大部分編碼收錄,這樣每個(gè)字符只有唯一的編碼。

但是 ASCII 碼只需要 1 個(gè)字節(jié)就可以存儲(chǔ),而 GBK 需要 2 個(gè)字節(jié),還有的字符集需要 3 個(gè)字節(jié)等,有的只要一個(gè)字節(jié)存儲(chǔ)卻存了 2 個(gè)字節(jié),比較浪費(fèi)空間。所以就出現(xiàn)了 utf-8、utf-16、utf-24 等不同編碼方案。

utf-8、utf-16、utf-24 都是 unicode 編碼,但是具體實(shí)現(xiàn)方案不同。

UTF-8 為了節(jié)省空間,設(shè)計(jì)了從 1 到 6 個(gè)字節(jié)的變長(zhǎng)存儲(chǔ)方案。而 UTF-16 是固定 2 個(gè)字節(jié),UTF-24 是固定 4 個(gè)字節(jié)。

聊聊Node.js Buffer中的encoding(編碼)

最后,UTF-8 因?yàn)檎加每臻g最少,所以被廣泛應(yīng)用。

Node.js 的 Buffer 的 encoding

每種語(yǔ)言都支持字符集的編碼解碼,Node.js 也同樣。

Node.js 里面可以通過(guò) Buffer 來(lái)存儲(chǔ)二進(jìn)制的數(shù)據(jù),而二進(jìn)制的數(shù)據(jù)轉(zhuǎn)為字符串的時(shí)候就需要指定字符集,Buffer 的 from、byteLength、lastIndexOf 等方法都支持指定 encoding:

具體支持的 encoding 有這些:

utf8、ucs2、utf16le、latin1、ascii、base64、hex

可能有的同學(xué)會(huì)發(fā)現(xiàn): base64、hex 不是字符集啊,怎么也出現(xiàn)在這里?

是的,字節(jié)到字符的編碼方案除了字符集之外,也有用于轉(zhuǎn)為明文字符的 base64、以及轉(zhuǎn)為 16 進(jìn)制的 hex。

這也是為什么 Node.js 把它叫做 encoding 而不是 charset,因?yàn)橹С值木幗獯a方案不只是字符集。

如果不指定 encoding,默認(rèn)是 utf8。

const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');  console.log(buf.toString());// hello world

encoding 的 源碼

我去翻了下 Node.js 關(guān)于 encoding 的源碼:

這一段是實(shí)現(xiàn) encoding 的:https://github.com/nodejs/node/blob/master/lib/buffer.js#L587-L726

可以看到每個(gè) encoding 都實(shí)現(xiàn)了 encoding、encodingVal、byteLength、write、slice、indexOf 這幾個(gè) api,因?yàn)檫@些 api 用不同 encoding 方案,會(huì)有不同的結(jié)果,Node.js 會(huì)根據(jù)傳入的 encoding 來(lái)返回不同的對(duì)象,這是一種多態(tài)的思想。

const encodingOps = {   utf8: {     encoding: 'utf8',     encodingVal: encodingsMap.utf8,     byteLength: byteLengthUtf8,     write: (buf, string, offset, len) => buf.utf8Write(string, offset, len),     slice: (buf, start, end) => buf.utf8Slice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir)   },   ucs2: {     encoding: 'ucs2',     encodingVal: encodingsMap.utf16le,     byteLength: (string) => string.length * 2,     write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len),     slice: (buf, start, end) => buf.ucs2Slice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir)   },   utf16le: {     encoding: 'utf16le',     encodingVal: encodingsMap.utf16le,     byteLength: (string) => string.length * 2,     write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len),     slice: (buf, start, end) => buf.ucs2Slice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir)   },   latin1: {     encoding: 'latin1',     encodingVal: encodingsMap.latin1,     byteLength: (string) => string.length,     write: (buf, string, offset, len) => buf.latin1Write(string, offset, len),     slice: (buf, start, end) => buf.latin1Slice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir)   },   ascii: {     encoding: 'ascii',     encodingVal: encodingsMap.ascii,     byteLength: (string) => string.length,     write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len),     slice: (buf, start, end) => buf.asciiSlice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfBuffer(buf,                     fromStringFast(val, encodingOps.ascii),                     byteOffset,                     encodingsMap.ascii,                     dir)   },   base64: {     encoding: 'base64',     encodingVal: encodingsMap.base64,     byteLength: (string) => base64ByteLength(string, string.length),     write: (buf, string, offset, len) => buf.base64Write(string, offset, len),     slice: (buf, start, end) => buf.base64Slice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfBuffer(buf,                     fromStringFast(val, encodingOps.base64),                     byteOffset,                     encodingsMap.base64,                     dir)   },   hex: {     encoding: 'hex',     encodingVal: encodingsMap.hex,     byteLength: (string) => string.length >>> 1,     write: (buf, string, offset, len) => buf.hexWrite(string, offset, len),     slice: (buf, start, end) => buf.hexSlice(start, end),     indexOf: (buf, val, byteOffset, dir) =>       indexOfBuffer(buf,                     fromStringFast(val, encodingOps.hex),                     byteOffset,                     encodingsMap.hex,                     dir)   } }; function getEncodingOps(encoding) {   encoding += '';   switch (encoding.length) {     case 4:       if (encoding === 'utf8') return encodingOps.utf8;       if (encoding === 'ucs2') return encodingOps.ucs2;       encoding = StringPrototypeToLowerCase(encoding);       if (encoding === 'utf8') return encodingOps.utf8;       if (encoding === 'ucs2') return encodingOps.ucs2;       break;     case 5:       if (encoding === 'utf-8') return encodingOps.utf8;       if (encoding === 'ascii') return encodingOps.ascii;       if (encoding === 'ucs-2') return encodingOps.ucs2;       encoding = StringPrototypeToLowerCase(encoding);       if (encoding === 'utf-8') return encodingOps.utf8;       if (encoding === 'ascii') return encodingOps.ascii;       if (encoding === 'ucs-2') return encodingOps.ucs2;       break;     case 7:       if (encoding === 'utf16le' ||           StringPrototypeToLowerCase(encoding) === 'utf16le')         return encodingOps.utf16le;       break;     case 8:       if (encoding === 'utf-16le' ||           StringPrototypeToLowerCase(encoding) === 'utf-16le')         return encodingOps.utf16le;       break;     case 6:       if (encoding === 'latin1' || encoding === 'binary')         return encodingOps.latin1;       if (encoding === 'base64') return encodingOps.base64;       encoding = StringPrototypeToLowerCase(encoding);       if (encoding === 'latin1' || encoding === 'binary')         return encodingOps.latin1;       if (encoding === 'base64') return encodingOps.base64;       break;     case 3:       if (encoding === 'hex' || StringPrototypeToLowerCase(encoding) === 'hex')         return encodingOps.hex;       break;   } }

總結(jié)

計(jì)算機(jī)中存儲(chǔ)數(shù)據(jù)的最小單位是位,但是存儲(chǔ)信息最小的單位是字節(jié),基于編碼和字符的映射關(guān)系又實(shí)現(xiàn)了各種字符集,包括 ascii、iso、gbk 等,而國(guó)際標(biāo)準(zhǔn)化組織提出了 unicode 來(lái)包含所有字符,unicode 實(shí)現(xiàn)方案有若干種:utf-8、utf-16、utf-24,他們分別用不同的字節(jié)數(shù)來(lái)存儲(chǔ)字符。其中 utf-8 是變長(zhǎng)的,存儲(chǔ)體積最小,所以被廣泛應(yīng)用。

Node.js 通過(guò) Buffer 存儲(chǔ)二進(jìn)制數(shù)據(jù),而轉(zhuǎn)為字符串時(shí)需要指定編碼方案,這個(gè)編碼方案不只是包含字符集(charset),也支持 hex、base64 的方案,包括:

utf8、ucs2、utf16le、latin1、ascii、base64、hex

我們看了下 encoding 的 Node.js 源碼,發(fā)現(xiàn)每種編碼方案都會(huì)用實(shí)現(xiàn)一系列 api,這是一種多態(tài)的思想。

encoding 是學(xué)習(xí) Node.js 頻繁遇到的一個(gè)概念,而且 Node.js 的 encoding 不只是包含 charset,希望這篇文章能夠幫大家了解編碼和字符集。

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
亚洲人精品午夜射精日韩| 日韩精品一二三四区| 97久久久精品综合88久久| 日产精品一线二线三线芒果| 国产啪精品视频网站免费尤物| 午夜精品久久久久久影视777| 六月婷婷精品视频在线观看| 日韩精品久久不卡中文字幕| 久热国产精品视频一区二区三区| 国产精品91在线| 亚洲国产精品网站久久| 99re在线精品视频免费| 久久精品国产亚洲AV麻豆不卡 | 国产真实伦偷精品| 国内精品视频一区二区八戒| 国产精品99久久久久久宅男小说| 欧乱色国产精品兔费视频| 亚洲精品熟女国产| 99re6这里只有精品| 久久亚洲精品国产精品| 久久久久久久99精品国产片| 久久青青成人亚洲精品| 久久成人精品视频| 久久精品国产一区二区三区日韩| 亚洲乱码精品久久久久..| 综合国产精品第一页| 田中瞳中文字幕久久精品| 亚洲日韩精品无码专区网址 | 精品亚洲456在线播放| 精品一久久香蕉国产二月| 国产精品第13页| 久久夜色精品国产噜噜亚洲a| 99热门精品一区二区三区无码| 久久6这里只有精品| 91精品免费国产高清在线| 日韩视频在线精品视频免费观看| 2021国产精品视频| 亚洲精品国产精品| 午夜精品福利在线| 国产自偷在线拍精品热| 日韩高清成人毛片不卡|