當年是看了樸靈的九淺一深 NodeJS 入門的 Node, 樸大大的書講實踐不多更多的篇幅用在了講原理上,道理聽了那麼多,後來開始在前端工程領域使用 NodeJS 卻到處掣肘,總結緣由發現 NodeJS 中難的部分無非是文件和網絡,文件操做和網絡都依賴了一個很重要的對象—— Stream,這偏偏是樸大大書中沒有說起的。javascript
Buffer 樸大大在書中是有提到過的,但由於流實際上就是在處理 Buffer,因此仍是要簡單總結一下。html
如同官方 API 中介紹的那樣,在 ES6 引入 TypedArray 以前,JavaScript 沒有讀取或者操做二進制數據流的機制。 Buffer 類做爲 NodeJS API 的一部分被引入,以便可以和 TCP 等網絡流和文件流等進行交互。前端
如今 TypedArray 已經被添加到了 ES6 中,Buffer 類以一種更優化和適用於 NodeJS 操做的方式實現了 Unit8Array API。java
總而言之,Buffer 類是用來處理二進制數據,由於太經常使用了,因此直接放在了全局變量裏,使用的時候無需 require。node
Buffer 類的實例相似於整型數組,不過緩衝區的大小在建立時肯定,不能調整。Buffer 對象不一樣之處在於它不經 V8 的內存分配機制,Buffer 是一個 JavaScript 和 C++ 結合的模塊,內存由 C++ 申請,JavaScript 分配。api
關於 Buffer 內存分配相關知識不展開討論,感興趣同窗能夠看看樸老溼的書。數組
在 NodeJS v6 以前都是經過調用構造函數的方式實例化 Buffer,根據參數返回不一樣結果。處於安全性緣由,這種方式在 v6 後的版本中已經被廢除,提供了安全
三個單獨的,職責清晰的函數處理實例化 Buffer 的工做。網絡
// 0x 表示 16 進制 Buffer.from([1, 2, 3]) // [0x1, 0x2, 0x3] Buffer.from('test', 'utf-8') // [0x74, 0x65, 0x73, 0x74] Buffer.alloc(5, 1) // [0x1, 0x1, 0x1, 0x1, 0x1] Buffer.allocUnsafe(5); // 值不肯定,後面詳談
Buffer.allocUnsafe()
的執行會快於 Buffer.alloc()
看名字很不安全,確實也不安全。函數
當調用 Buffer.allocUnsafe()
時分配的內存段還沒有初始化(不歸零),這樣分配內存速度很塊,但分配到的內存片斷可能包含舊數據。若是在使用的時候不覆蓋這些舊數據就可能形成內存泄露,雖然速度快,儘可能避免使用。
Buffer 支持如下幾種編碼格式
字符串轉爲 Buffer 比較簡單
Buffer.from(string [, encoding])
同時 Buffer 實例也有 toString 方法將 Buffer 轉爲字符串
buf.toString([encoding[, start[, end]]])
使用 concat 方法能夠講多個 Buffer 實例拼接爲一個 Buffer 實例
Buffer.concat(list[, totalLength])
在 NodeJS 中一個漢字由三個字節表示,若是咱們處理中文字符的時候使用了不是3的倍數的字節數就會形成字符拼接亂碼問題。
const buf = Buffer.from('中文字符串!'); for(let i = 0; i < buf.length; i+=5){ var b = Buffer.allocUnsafe(5); buf.copy(b, 0, i); console.log(b.toString()); }
這樣能夠看到結果中出現了亂碼
但若是使用 string_decoder 模塊即可以解決這個問題
const StringDecoder = require('string_decoder').StringDecoder; const decoder = new StringDecoder('utf8'); const buf = Buffer.from('中文字符串!'); for(let i = 0; i < buf.length; i+=5){ var b = Buffer.allocUnsafe(5); buf.copy(b, 0, i); console.log(decoder.write(b)); }
StringDecoder 在獲得編碼後,知道寬字節在utf-8下佔3個字節,因此在處理末尾不全的字節時,會保留到第二次 write()。目前只能處理UTF-八、Base64 和 UCS-2/UTF-16LE。
還有一些 Buffer 經常使用的 API