Buffer存在於全局對象上,無需引入模塊便可使用,可見重要性非同通常。
能夠理解Buffer是在內存中開闢的一片區域,用於存放二進制數據。Buffer所開闢的是堆外內存。html
怎麼理解流呢?流是數據的集合(與數據、字符串相似),可是流的數據不能一次性獲取到,數據也不會所有load到內存中,所以流很是適合大數據處理以及斷斷續續返回chunk的外部源。流的生產者與消費者之間的速度一般是不一致的,所以須要buffer來暫存一些數據。buffer大小經過highWaterMark參數指定,默認狀況下是16Kb。node
Buffer 對象佔用的內存空間是不計算在 Node.js 進程內存空間限制上的,因此能夠用來存儲大對象,可是對象的大小仍是有限制的。通常狀況下32位系統大約是1G,64位系統大約是2G。linux
除了流自動隱式建立Buffer以外,也能夠手動建立Buffer,方式以下:git
Buffer.from(obj) // obj支持的類型string, buffer, arrayBuffer, array, or array-like objectgithub
注意:Buffer.from不支持傳入數字,以下所示:json
Buffer.from(1234); buffer.js:208 throw new errors.TypeError( ^ TypeError [ERR_INVALID_ARG_TYPE]: The "value" argument must not be of type number. Received type number at Function.from (buffer.js:208:11) ...
若要傳入數字能夠採用傳入數組的方式:數組
const buf = Buffer.from([1, 2, 3, 4]); console.log(buf); //
可是這種方式存在一個問題,當存入不一樣的數值的時候buffer中記錄的二進制數據會相同,以下所示:安全
const buf2 = Buffer.from([127, -1]); console.log(buf2); const buf3 = Buffer.from([127, 255]); console.log(buf3); console.log(buf3.equals(buf2)); // true
當要記錄的一組數所有落在0到255(readUInt8來讀取)這個範圍, 或者所有落在-128到127(readInt8來讀取)這個範圍那麼就沒有問題,不然的話就強烈不推薦使用Buffer.from來保存一組數。由於不一樣的數字讀取時應該調用不一樣的方法。大數據
Buffer.alloc、Buffer.allocUnsafe、Buffer.allocUnsafeSlowui
Buffer.alloc會用0值填充已分配的內存,因此相比後二者速度上要慢,可是也較爲安全。固然也能夠經過--zero-fill-buffers flag使allocUnsafe、allocUnsafeSlow在分配完內存後也進行0值填充。
node --zero-fill-buffers index.js
當分配的空間小於4KB的時候,allocUnsafe會直接從以前預分配的Buffer裏面slice空間,所以速度比allocUnsafeSlow要快,當大於等於4KB的時候兩者速度相差無異。
// 分配空間等於 function createBuffer(fn, size) { console.time('buf-' + fn); for (var i = 0; i < 100000; i++) { Buffer[fn](size); } console.timeEnd('buf-' + fn); } createBuffer('alloc', 4096); createBuffer('allocUnsafe', 4096); createBuffer('allocUnsafeSlow', 4096); // 輸出 buf-alloc: 294.002ms buf-allocUnsafe: 224.072ms buf-allocUnsafeSlow: 209.22ms
function createBuffer(fn, size) { console.time('buf-' + fn); for (var i = 0; i < 100000; i++) { Buffer[fn](size); } console.timeEnd('buf-' + fn); } createBuffer('alloc', 4095); createBuffer('allocUnsafe', 4095); createBuffer('allocUnsafeSlow', 4095); // 輸出 buf-alloc: 296.965ms buf-allocUnsafe: 135.877ms buf-allocUnsafeSlow: 205.225ms
須要謹記一點:new Buffer(xxxx) 方式已經不推薦使用了
const buf = Buffer.from('test'); console.log(buf.toString('utf8')); // test console.log(buf.toString('utf8', 0, 2)); // te
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); console.log(buf.toJSON()); // { type: 'Buffer', data: [ 1, 2, 3, 4, 5 ] }
buf.slice([start[, end]]) start 起始位置 end 結束位置(不包含) 示例: var buf1 = Buffer.from('test'); var buf2 = buf1.slice(1, 3).fill('xx'); console.log("buf2 content: " + buf2.toString()); // xx console.log("buf1 content: " + buf1.toString()); // txxt
buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]]) 示例: var buf1 = Buffer.from('abcdefghijkl'); var buf2 = Buffer.from('ABCDEF'); buf1.copy(buf2, 1); console.log(buf2.toString()); //Abcdef
buf.equals(otherBuffer) 示例: const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('414243', 'hex'); console.log(buf1.equals(buf2)); // true
除了equals以外,compare其實也能夠用於判斷是否相等(當結果爲0則相等),不過compare更主要的做用是用於對數組內的buffer實例排序。
buf.includes(value[, byteOffset][, encoding]) buf.indexOf(value[, byteOffset][, encoding]) 示例: const buf = Buffer.from('this is a buffer'); console.log(buf.includes('this')); // true console.log(buf.indexOf('this')); // 0
寫入方法:
write{Double| Float | Int16 | Int32| UInt16 | UInt32 }{BE|LE}(value, offset)
write{Int | UInt}{BE | LE}(value, offset, bytelength) // 此方法提供了更靈活的位數表示數據(好比3位、5位)
write{Int8 | Unit8}(value, offset)
讀取方法:
write{Double| Float | Int16 | Int32 | UInt16 | UInt32 }{BE|LE}(offset)
read{Int | UInt}{BE | LE}(offset, byteLength)
read{Int8 | Unit8}(offset)
Double、Float、Int1六、Int3二、UInt1六、UInt32既肯定了表徵數字的位數,也肯定了是否包含負數,所以定義了不一樣的數據範圍。同時因爲表徵數字的位數都超過8位,沒法用一個字節來表示,所以就涉及到了計算機的字節序區分(大端字節序與小端字節序)
關於大端小端的區別能夠這麼理解:數值的高位在buffer的起始位置的是大端,數值的低位buffer的起始位置則是小端
const buf = Buffer.allocUnsafe(2); buf.writeInt16BE(256, 0) console.log(buf); // <Buffer 01 00> buf.writeInt16LE(256, 0) console.log(buf); // <Buffer 00 01>
https://tool.lu/hexconvert/ 這裏能夠查看數值的不一樣進制之間的轉換,若是是大端的話,則直接按順序(0100)拼接16進制便可,若是是小端則須要調換一下順序纔是正確的表示方式。
Buffer.concat(list[, totalLength]) //totalLength不是必須的,若是不提供的話會爲了計算totalLength會多一次遍歷 const buf1 = Buffer.from('this is'); const buf2 = Buffer.from(' funny'); console.log(Buffer.concat([buf1, buf2], buf1.length + buf2.length)); // <Buffer 74 68 69 73 20 69 73 20 66 75 6e 6e 79>
清空buffer數據最快的辦法是buffer.fill(0)
Buffer是全局global上的一個引用,指向的實際上是buffer.Buffer
const buffer = require('buffer'); console.log(buffer.Buffer === Buffer); //true
buffer模塊上還有其餘一些屬性和方法
const buffer = require('buffer'); console.log(buffer); { Buffer: { [Function: Buffer] poolSize: 8192, from: [Function: from], alloc: [Function: alloc], allocUnsafe: [Function: allocUnsafe], allocUnsafeSlow: [Function: allocUnsafeSlow], isBuffer: [Function: isBuffer], compare: [Function: compare], isEncoding: [Function: isEncoding], concat: [Function: concat], byteLength: [Function: byteLength], [Symbol(node.isEncoding)]: [Function: isEncoding] }, SlowBuffer: [Function: SlowBuffer], transcode: [Function: transcode], INSPECT_MAX_BYTES: 50, kMaxLength: 2147483647, kStringMaxLength: 1073741799, constants: { MAX_LENGTH: 2147483647, MAX_STRING_LENGTH: 1073741799 } }
上面的kMaxLength與MAX_LENGTH表明了新建buffer時內存大小的最大值,當超過限制值後就會報錯
32爲機器上是(2^30)-1
(~1GB)
64位機器上是(2^31)-1
(~2GB)
咱們沒法手動對buffer實例進行GC,只能依靠V8來進行,咱們惟一能作的就是解除對buffer實例的引用
http://cenalulu.github.io/lin...
http://www.ruanyifeng.com/blo...
https://medium.freecodecamp.o...
https://www.barretlee.com/blo...