自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入理解 Node.js Buffer 的 Encoding

開(kāi)發(fā) 前端
計(jì)算機(jī)最小的單位是一個(gè)位,也就是 0 和 1,在硬件上通過(guò)高低電平來(lái)對(duì)應(yīng)。但是只有一位表示的信息太少了,所以又規(guī)定了 8 個(gè)位為一個(gè)字節(jié),之后數(shù)字、字符串等各種信息都是基于字節(jié)來(lái)存儲(chǔ)的。

 

[[419669]]

字符怎么存儲(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é)。

最后,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。

  1. const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=''base64'); 
  2.  
  3. 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)的思想。

  1. const encodingOps = { 
  2.   utf8: { 
  3.     encoding: 'utf8'
  4.     encodingVal: encodingsMap.utf8, 
  5.     byteLength: byteLengthUtf8, 
  6.     write: (buf, string, offset, len) => buf.utf8Write(string, offset, len), 
  7.     slice: (buf, start, end) => buf.utf8Slice(start, end), 
  8.     indexOf: (buf, val, byteOffset, dir) => 
  9.       indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir) 
  10.   }, 
  11.   ucs2: { 
  12.     encoding: 'ucs2'
  13.     encodingVal: encodingsMap.utf16le, 
  14.     byteLength: (string) => string.length * 2, 
  15.     write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 
  16.     slice: (buf, start, end) => buf.ucs2Slice(start, end), 
  17.     indexOf: (buf, val, byteOffset, dir) => 
  18.       indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 
  19.   }, 
  20.   utf16le: { 
  21.     encoding: 'utf16le'
  22.     encodingVal: encodingsMap.utf16le, 
  23.     byteLength: (string) => string.length * 2, 
  24.     write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 
  25.     slice: (buf, start, end) => buf.ucs2Slice(start, end), 
  26.     indexOf: (buf, val, byteOffset, dir) => 
  27.       indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 
  28.   }, 
  29.   latin1: { 
  30.     encoding: 'latin1'
  31.     encodingVal: encodingsMap.latin1, 
  32.     byteLength: (string) => string.length, 
  33.     write: (buf, string, offset, len) => buf.latin1Write(string, offset, len), 
  34.     slice: (buf, start, end) => buf.latin1Slice(start, end), 
  35.     indexOf: (buf, val, byteOffset, dir) => 
  36.       indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir) 
  37.   }, 
  38.   ascii: { 
  39.     encoding: 'ascii'
  40.     encodingVal: encodingsMap.ascii, 
  41.     byteLength: (string) => string.length, 
  42.     write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len), 
  43.     slice: (buf, start, end) => buf.asciiSlice(start, end), 
  44.     indexOf: (buf, val, byteOffset, dir) => 
  45.       indexOfBuffer(buf, 
  46.                     fromStringFast(val, encodingOps.ascii), 
  47.                     byteOffset, 
  48.                     encodingsMap.ascii, 
  49.                     dir) 
  50.   }, 
  51.   base64: { 
  52.     encoding: 'base64'
  53.     encodingVal: encodingsMap.base64, 
  54.     byteLength: (string) => base64ByteLength(string, string.length), 
  55.     write: (buf, string, offset, len) => buf.base64Write(string, offset, len), 
  56.     slice: (buf, start, end) => buf.base64Slice(start, end), 
  57.     indexOf: (buf, val, byteOffset, dir) => 
  58.       indexOfBuffer(buf, 
  59.                     fromStringFast(val, encodingOps.base64), 
  60.                     byteOffset, 
  61.                     encodingsMap.base64, 
  62.                     dir) 
  63.   }, 
  64.   hex: { 
  65.     encoding: 'hex'
  66.     encodingVal: encodingsMap.hex, 
  67.     byteLength: (string) => string.length >>> 1, 
  68.     write: (buf, string, offset, len) => buf.hexWrite(string, offset, len), 
  69.     slice: (buf, start, end) => buf.hexSlice(start, end), 
  70.     indexOf: (buf, val, byteOffset, dir) => 
  71.       indexOfBuffer(buf, 
  72.                     fromStringFast(val, encodingOps.hex), 
  73.                     byteOffset, 
  74.                     encodingsMap.hex, 
  75.                     dir) 
  76.   } 
  77. }; 
  78. function getEncodingOps(encoding) { 
  79.   encoding += ''
  80.   switch (encoding.length) { 
  81.     case 4: 
  82.       if (encoding === 'utf8'return encodingOps.utf8; 
  83.       if (encoding === 'ucs2'return encodingOps.ucs2; 
  84.       encoding = StringPrototypeToLowerCase(encoding); 
  85.       if (encoding === 'utf8'return encodingOps.utf8; 
  86.       if (encoding === 'ucs2'return encodingOps.ucs2; 
  87.       break; 
  88.     case 5: 
  89.       if (encoding === 'utf-8'return encodingOps.utf8; 
  90.       if (encoding === 'ascii'return encodingOps.ascii; 
  91.       if (encoding === 'ucs-2'return encodingOps.ucs2; 
  92.       encoding = StringPrototypeToLowerCase(encoding); 
  93.       if (encoding === 'utf-8'return encodingOps.utf8; 
  94.       if (encoding === 'ascii'return encodingOps.ascii; 
  95.       if (encoding === 'ucs-2'return encodingOps.ucs2; 
  96.       break; 
  97.     case 7: 
  98.       if (encoding === 'utf16le' || 
  99.           StringPrototypeToLowerCase(encoding) === 'utf16le'
  100.         return encodingOps.utf16le; 
  101.       break; 
  102.     case 8: 
  103.       if (encoding === 'utf-16le' || 
  104.           StringPrototypeToLowerCase(encoding) === 'utf-16le'
  105.         return encodingOps.utf16le; 
  106.       break; 
  107.     case 6: 
  108.       if (encoding === 'latin1' || encoding === 'binary'
  109.         return encodingOps.latin1; 
  110.       if (encoding === 'base64'return encodingOps.base64; 
  111.       encoding = StringPrototypeToLowerCase(encoding); 
  112.       if (encoding === 'latin1' || encoding === 'binary'
  113.         return encodingOps.latin1; 
  114.       if (encoding === 'base64'return encodingOps.base64; 
  115.       break; 
  116.     case 3: 
  117.       if (encoding === 'hex' || StringPrototypeToLowerCase(encoding) === 'hex'
  118.         return encodingOps.hex; 
  119.       break; 
  120.   } 

總結(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-32,他們分別用不同的字節(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)的思想。

 

責(zé)任編輯:武曉燕 來(lái)源: 神光的編程秘籍
相關(guān)推薦

2021-10-16 05:00:32

.js Buffer模塊

2021-08-05 05:46:06

Node.jsInspector工具

2021-08-12 01:00:29

NodejsAsync

2021-09-01 13:32:48

Node.jsAPI POSIX

2021-09-10 06:50:03

Node.jsSocket端口

2013-11-01 09:34:56

Node.js技術(shù)

2019-08-15 14:42:24

進(jìn)程線程javascript

2013-06-14 09:27:51

Express.jsJavaScript

2021-05-27 09:00:00

Node.js開(kāi)發(fā)線程

2024-01-05 08:49:15

Node.js異步編程

2015-07-16 09:59:55

PHP Node.js討論

2017-08-16 10:36:10

JavaScriptNode.js事件驅(qū)動(dòng)

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過(guò)濾器

2015-03-10 10:59:18

Node.js開(kāi)發(fā)指南基礎(chǔ)介紹

2020-08-31 15:00:17

Node.jsrequire前端

2020-05-29 15:33:28

Node.js框架JavaScript

2012-02-03 09:25:39

Node.js

2021-12-25 22:29:57

Node.js 微任務(wù)處理事件循環(huán)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)