NodeJS 難點(網絡,文件)的 核心 stream 一:Buffer


stream應用一圖片轉存服務

 

stream github教程

 

文件操作和網絡都依賴了一個很重要的對象—— Stream, 而這個 <node深入淺出> 沒有分析的,  

所以讀完這本書, 在實踐中還會遇到很多困難

 

stream 是處理 buffer

JavaScript 沒有讀取或者操作二進制數據流的機制。

Buffer 類作為 NodeJS API 的一部分被引入,以便能夠和 TCP 等網絡流和文件流等進行交互。

 

總而言之,Buffer 類是用來處理二進制數據,

因為太常用了,所以直接放在了全局變量里,使用的時候無需 require。

 

Buffer 類的實例類似於整型數組,不過緩沖區的大小在創建時確定,不能調整。

Buffer 對象不同之處在於它不經 V8 的內存分配機制,Buffer 是一個 JavaScript 和 C++ 結合的模塊,內存由 C++ 申請,JavaScript 分配。

 

實例化 Buffer

在 NodeJS v6 之前都是通過調用構造函數的方式實例化 Buffer,根據參數返回不同結果。處於安全性原因,這種方式在 v6 后的版本中已經被廢除,提供了

  • Buffer.from()
  • Buffer.alloc()
  • Buffer.allocUnsafe()

三個單獨的,職責清晰的函數處理實例化 Buffer 的工作。

  • Buffer.from(array):返回一個內容包含所提供的字節副本的 Buffer,數組中每一項是一個表示八位字節的數字,所以值必須在 0 ~ 255 之間,否則會取模
  • Buffer.from(arrayBuffer):返回一個與給定的 ArrayBuffer 共享內存的新 Buffer
  • Buffer.from(buffer):返回給定 Buffer 的一個副本 Buffer
  • Buffer.from(string [, encoding]):返回一個包含給定字符串的 Buffer
  • Buffer.alloc(size [, fill [, encoding]]):返回指定大小並且“已填充”的 Buffer
  • Buffer.allocUnsafe(size):返回指定大小的 Buffer,內容必須用 buf.fill(0) 等方法填充, 一般不實用
// 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 支持以下幾種編碼格式

  • ascii
  • utf8
  • utf16le
  • base64
  • binary
  • hex

Buffer 和 String 轉換

字符串轉為 Buffer 比較簡單

Buffer.from(string [, encoding])

同時 Buffer 實例也有 toString 方法將 Buffer 轉為字符串

buf.toString([encoding[, start[, end]]])

Buffer 拼接

使用 concat 方法可以講多個 Buffer 實例拼接為一個 Buffer 實例

Buffer.concat(list[, totalLength])

StringDecoder

在 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-8、Base64 和 UCS-2/UTF-16LE。

Buffer 其它常用 API

還有一些 Buffer 常用的 API

  • Buffer.isBuffer:判斷對象是否為 Buffer
  • Buffer.isEncoding:判斷 Buffer 對象編碼
  • buf.length:返回 內存為此 Buffer 實例所申請的字節數,並不是 Buffer 實例內容的字節數
  • buf.indexOf:和數組的 indexOf 類似,返回某字符串、acsii 碼或者 buf 在改 buf 中的位置
  • buf.copy:將一個 buf 的(部分)內容復制到另外一個 buf 中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM