Node.js | Buffer(緩衝區)
簡介
JavaScript
語言自身只有字符串資料類型,沒有二進制資料類型。
但在處理像TCP
流或文件流時,必須使用到二進制資料。因此在Node.js
中,定義了一個Buffer
類,該類用來建立一個專門存放二進制資料的緩存區。
在Node.js
中,Buffer
類是隨Node
內核一起發布的核心庫。Buffer
庫為Node.js
帶來了一種存儲原始資料的方法,可以讓Node.js
處理二進制資料,每當需要在Node.js
中處理I/O
操作中移動的資料時,就有可能使用Buffer
庫。原始資料存儲在Buffer
類的實例中。一個 Buffer
類似於一個整數數組,但它對應於V8
堆內存之外的一塊原始內存。
註:在v6.0之前建立Buffer對象直接使用new Buffer()構造函數來建立對象實例,但是Buffer對內存的權限操作相比很大,可以直接捕獲一些敏感訊息,所以在v6.0以後,官方文件裡面建議使用Buffer.from()接口去建立Buffer對象。
註:詳細Doc Link
Buffer 與字符編碼
Buffer
實例一般用於表示編碼字符的序列,比如UTF-8
、UCS2
、Base64
、或十六進制編碼的資料。通過使用顯式的字符編碼,就可以在 Buffer
實例與普通的JavaScript
字符串之間進行相互轉換。
1 | const buf = Buffer.from('morosedog', 'ascii'); |
Node.js
目前支持的字符編碼包括:
名稱 | 說明 |
---|---|
ascii | 僅支持 7 位 ASCII 資料。如果設置去掉高位的話,這種編碼是非常快的。 |
utf8 | 多字節編碼的 Unicode 字符。許多網頁和其他文件格式都使用 UTF-8 。 |
utf16le | 2 或 4 個字節,小字節序編碼的 Unicode 字符。支持代理對(U+10000 至 U+10FFFF)。 |
ucs2 | utf16le 的別名。 |
base64 | Base64 編碼。 |
latin1 | 一種把 Buffer 編碼成一字節編碼的字符串的方式。 |
binary | latin1 的別名。 |
hex | 將每個字節編碼為兩個十六進製字符。 |
建立 Buffer 類
Buffer
提供了以下API
來建立Buffer
類:
名稱 | 說明 |
---|---|
Buffer.alloc(size[, fill[, encoding]]) | 返回一個指定大小的 Buffer 實例,如果沒有設置 fill,則默認填滿 0 |
Buffer.allocUnsafe(size) | 返回一個指定大小的 Buffer 實例,但是它不會被初始化,所以它可能包含敏感的資料Buffer.allocUnsafeSlow(size) |
Buffer.from(array) | 返回一個被 array 的值初始化的新的 Buffer 實例(傳入的 array 的元素只能是數字,不然就會自動被 0 覆蓋) |
Buffer.from(arrayBuffer[, byteOffset[, length]]) | 返回一個新建的與給定的 ArrayBuffer 共享同一內存的 Buffer。 |
Buffer.from(buffer) | 複製傳入的 Buffer 實例的資料,並返回一個新的 Buffer 實例 |
Buffer.from(string[, encoding]) | 返回一個被 string 的值初始化的新的 Buffer 實例 |
1 | // 建立一個長度為 10、且用 0 填充的 Buffer。 |
執行結果如下:
1 | $ node main.js |
寫入緩衝區
語法
寫入Node
緩衝區的語法如下所示:
1 | buf.write(string[, offset[, length]][, encoding]) |
參數
參數描述如下:
string
:寫入緩衝區的字符串。offset
:緩衝區開始寫入的索引值,默認為0
。length
:寫入的字節數,默認為buffer.length
。encoding
:使用的編碼。默認為'utf8'
。
根據encoding
的字符編碼寫入string
到buf
中的offset
位置。length
參數是寫入的字節數。如果buf
沒有足夠的空間保存整個字符串,則只會寫入string
的一部分。只部分解碼的字符不會被寫入。
返回值
返回實際寫入的大小。如果buffer
空間不足,則只會寫入部分字符串。
實例
1 | buf = Buffer.alloc(256); |
執行結果如下:
1 | $node main.js |
從緩衝區讀取資料
語法
讀取Node
緩衝區資料的語法如下所示:
1 | buf.toString([encoding[, start[, end]]]) |
參數
參數描述如下:
encoding
:使用的編碼。默認為'utf8'
。start
:指定開始讀取的索引位置,默認為0
。end
:結束位置,默認為緩衝區的末尾。
返回值
解碼緩衝區資料並使用指定的編碼返回字符串。
實例
1 | buf = Buffer.alloc(26); |
執行結果如下:
1 | $ node main.js |
補充:ASCII表
將 Buffer 轉換為 JSON 對象
語法
將Node Buffer
轉換為JSON
對象的函數語法格式如下:
1 | buf.toJSON() |
當字符串化一個Buffe
實例時,JSON.stringify()
會隱式地調用該toJSON()
。
返回值
返回JSON
對象。
實例
1 | const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); |
執行結果如下:
1 | {"type":"Buffer","data":[1,2,3,4,5]} |
緩衝區合併
語法
Node
緩衝區合併的語法如下所示:
1 | Buffer.concat(list[, totalLength]) |
參數
參數描述如下:
list
:用於合併的Buffer
對像數組列表。totalLength
:指定合併後Buffer
對象的總長度。
返回值
返回一個多個成員合併的新Buffer
對象。
實例
1 | var buffer1 = Buffer.from(("J.J.'s Blogs 技術筆記")); |
執行結果如下:
1 | $ node main.js |
緩衝區比較
語法
Node Buffer
比較的函數語法如下所示,該方法在Node.js v0.12.2
版本引入:
1 | buf.compare(otherBuffer); |
參數
參數描述如下:
otherBuffe
:與buf
對像比較的另外一個Buffer
對象。
返回值
返回一個數字,表示buf
在otherBuffer
之前,之後或相同。
實例
1 | var buffer1 = Buffer.from('ABC'); |
執行結果如下:
1 | $ node main.js |
拷貝緩衝區
語法
Node
緩衝區拷貝語法如下所示:
1 | buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) |
參數
參數描述如下:
targetBuffer
:要拷貝的Buffer
對象。targetStart
:數字,可選,默認:0
。sourceStart
:數字,可選,默認:0
。sourceEnd
:數字,可選,默認:buffer.length
。
返回值
沒有返回值。
實例
1 | var buf1 = Buffer.from('abcdefghijkl'); |
執行結果如下:
1 | $ node main.js |
緩衝區裁剪
語法
Node
緩衝區裁剪語法如下所示:
1 | buf.slice([start[, end]]) |
參數
參數描述如下:
start
:數字,可選,默認:0
。end
:數字,可選,默認:buffer.length
。
返回值
返回一個新的緩衝區,它和舊緩衝區指向同一塊內存,但是從索引start
到end
的位置剪切。
實例
1 | var buffer1 = Buffer.from('morose'); |
執行結果如下:
1 | buffer2 content: mo |
緩衝區長度
語法
Node
緩衝區長度計算語法如下所示:
1 | buf.length; |
返回值
返回Buffer
對象所佔據的內存長度。
實例
1 | var buffer = Buffer.from('https://morosedog.gitlab.io/'); |
執行結果如下:
1 | $ node main.js |
方法參考手冊
以下列出了Node.js Buffer
模組常用的方法(注意有些方法在舊版本是沒有的):
序號 | 方法 & 描述 |
---|---|
1 | new Buffer(size) 分配一個新的 size 大小單位為8位字節的 buffer。注意, size 必須小於 kMaxLength,否則,將會拋出異常 RangeError。廢棄的: 使用 Buffer.alloc() 代替(或 Buffer.allocUnsafe())。 |
2 | new Buffer(buffer) 拷貝參數 buffer 的資料到 Buffer 實例。廢棄的: 使用 Buffer.from(buffer) 代替。 |
3 | new Buffer(str[, encoding]) 分配一個新的 buffer ,其中包含著傳入的 str 字符串。 encoding 編碼方式默認為 ‘utf8’。廢棄的: 使用 Buffer.from(string[, encoding]) 代替。 |
4 | buf.length 返回這個 buffer 的 bytes 數。注意這未必是 buffer 裡面內容的大小。 length 是 buffer 對象所分配的內存數,它不會隨著這個 buffer 對象內容的改變而改變。 |
5 | buf.write(string[, offset[, length]][, encoding]) 根據參數 offset 偏移量和指定的 encoding 編碼方式,將參數 string 資料寫入buffer。 offset 偏移量默認值是 0, encoding 編碼方式默認是 utf8。 length 長度是將要寫入的字符串的 bytes 大小。返回 number 類型,表示寫入了多少 8 位字節流。如果 buffer 沒有足夠的空間來放整個 string,它將只會只寫入部分字符串。 length 默認是 buffer.length - offset。這個方法不會出現寫入部分字符。 |
6 | buf.writeUIntLE(value, offset, byteLength[, noAssert]) 將value 寫入到buffer 裡, 它由offset 和byteLength 決定,最高支持48 位無符號整數,小端對齊。 |
7 | buf.writeUIntBE(value, offset, byteLength[, noAssert]) 將value 寫入到buffer 裡, 它由offset 和byteLength 決定,最高支持48 位無符號整數,大端對齊。 noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。 |
8 | buf.writeIntLE(value, offset, byteLength[, noAssert]) 將value 寫入到buffer 裡, 它由offset 和byteLength 決定,最高支持48位有符號整數,小端對齊。 noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。默認是 false。 |
9 | buf.writeIntBE(value, offset, byteLength[, noAssert]) 將value 寫入到buffer 裡, 它由offset 和byteLength 決定,最高支持48位有符號整數,大端對齊。 noAssert 值為 true 時,不再驗證 value 和 offset 的有效性。默認是 false。 |
10 | buf.readUIntLE(offset, byteLength[, noAssert]) 支持讀取 48 位以下的無符號數字,小端對齊。 noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,默認為 false。 |
11 | buf.readUIntBE(offset, byteLength[, noAssert]) 支持讀取 48 位以下的無符號數字,大端對齊。 noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,默認為 false。 |
12 | buf.readIntLE(offset, byteLength[, noAssert]) 支持讀取 48 位以下的有符號數字,小端對齊。 noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,默認為 false。 |
13 | buf.readIntBE(offset, byteLength[, noAssert]) 支持讀取 48 位以下的有符號數字,大端對齊。 noAssert 值為 true 時, offset 不再驗證是否超過 buffer 的長度,默認為 false。 |
14 | buf.toString([encoding[, start[, end]]]) 根據 encoding 參數(默認是 ‘utf8’)返回一個解碼過的 string 類型。還會根據傳入的參數 start (默認是 0) 和 end (默認是 buffer.length)作為取值範圍。 |
15 | buf.toJSON() 將 Buffer 實例轉換為 JSON 對象。 |
16 | buf[index] 獲取或設置指定的字節。返回值代表一個字節,所以返回值的合法範圍是十六進制0x00到0xFF 或者十進制0至 255。 |
17 | buf.equals(otherBuffer) 比較兩個緩衝區是否相等,如果是返回 true,否則返回 false。 |
18 | buf.compare(otherBuffer) 比較兩個 Buffer 對象,返回一個數字,表示 buf 在 otherBuffer 之前,之後或相同。 |
19 | buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) buffer 拷貝,源和目標可以相同。 targetStart 目標開始偏移和 sourceStart 源開始偏移默認都是 0。 sourceEnd 源結束位置偏移默認是源的長度 buffer.length 。 |
20 | buf.slice([start[, end]]) 剪切 Buffer 對象,根據 start(默認是 0 ) 和 end (默認是 buffer.length ) 偏移和裁剪了索引。負的索引是從 buffer 尾部開始計算的。 |
21 | buf.readUInt8(offset[, noAssert]) 根據指定的偏移量,讀取一個無符號 8 位整數。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。如果這樣 offset 可能會超出buffer 的末尾。默認是 false。 |
22 | buf.readUInt16LE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 字節序格式讀取一個無符號 16 位整數。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出 buffer 的末尾。默認是 false。 |
23 | buf.readUInt16BE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 字節序格式讀取一個無符號 16 位整數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出 buffer 的末尾。默認是 false。 |
24 | buf.readUInt32LE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個無符號 32 位整數,小端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
25 | buf.readUInt32BE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個無符號 32 位整數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
26 | buf.readInt8(offset[, noAssert]) 根據指定的偏移量,讀取一個有符號 8 位整數。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出 buffer 的末尾。默認是 false。 |
27 | buf.readInt16LE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 格式讀取一個 有符號 16 位整數,小端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出 buffer 的末尾。默認是 false。 |
28 | buf.readInt16BE(offset[, noAssert]) 根據指定的偏移量,使用特殊的 endian 格式讀取一個 有符號 16 位整數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出 buffer 的末尾。默認是 false。 |
29 | buf.readInt32LE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個有符號 32 位整數,小端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
30 | buf.readInt32BE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個有符號 32 位整數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
31 | buf.readFloatLE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個 32 位雙浮點數,小端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer的末尾。默認是 false。 |
32 | buf.readFloatBE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian 字節序格式讀取一個 32 位雙浮點數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer的末尾。默認是 false。 |
33 | buf.readDoubleLE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian字節序格式讀取一個 64 位雙精度數,小端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
34 | buf.readDoubleBE(offset[, noAssert]) 根據指定的偏移量,使用指定的 endian字節序格式讀取一個 64 位雙精度數,大端對齊。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 offset 可能會超出buffer 的末尾。默認是 false。 |
35 | buf.writeUInt8(value, offset[, noAssert]) 根據傳入的 offset 偏移量將 value 寫入 buffer。注意:value 必須是一個合法的無符號 8 位整數。若參數 noAssert 為 true 將不會驗證 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則不要使用。默認是 false。 |
36 | buf.writeUInt16LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的無符號 16 位整數,小端對齊。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出buffer的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
37 | buf.writeUInt16BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的無符號 16 位整數,大端對齊。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出buffer的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
38 | buf.writeUInt32LE(value, offset[, noAssert]) 根據傳入的offset 偏移量和指定的endian 格式(LITTLE-ENDIAN:小字節序)將value 寫入buffer 。注意:value 必須是一個合法的無符號 32 位整數,小端對齊。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著value 可能過大,或者offset可能會超出buffer的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
39 | buf.writeUInt32BE(value, offset[, noAssert]) 根據傳入的offset 偏移量和指定的endian 格式(Big-Endian:大字節序)將value 寫入buffer 。注意:value 必須是一個合法的有符號 32 位整數。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者offset可能會超出buffer的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
40 | buf.writeInt8(value, offset[, noAssert]) |
41 | buf.writeInt16LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 16 位整數。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false 。 |
42 | buf.writeInt16BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 16 位整數。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false 。 |
43 | buf.writeInt32LE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 32 位整數。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
44 | buf.writeInt32BE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個合法的 signed 32 位整數。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
45 | buf.writeFloatLE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer 。注意:當 value 不是一個 32 位浮點數類型的值時,結果將是不確定的。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
46 | buf.writeFloatBE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer 。注意:當 value 不是一個 32 位浮點數類型的值時,結果將是不確定的。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value可能過大,或者 offset 可能會超出 buffer 的末尾從而造成 value 被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
47 | buf.writeDoubleLE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個有效的 64 位double 類型的值。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成value被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
48 | buf.writeDoubleBE(value, offset[, noAssert]) 根據傳入的 offset 偏移量和指定的 endian 格式將 value 寫入 buffer。注意:value 必須是一個有效的 64 位double 類型的值。若參數 noAssert 為 true 將不會驗證 value 和 offset 偏移量參數。這意味著 value 可能過大,或者 offset 可能會超出 buffer 的末尾從而造成value被丟棄。除非你對這個參數非常有把握,否則盡量不要使用。默認是 false。 |
49 | buf.fill(value[, offset][, end]) 使用指定的 value 來填充這個 buffer。如果沒有指定 offset (默認是 0) 並且 end (默認是 buffer.length) ,將會填充整個buffer。 |
補充
1 | buf.compare(otherBuffer); |
這個方法是按位比較的。buffer1.compare(buffer2)
,這個方法是按位比較的。buffer1
的第一位比較buffer2
的第一位,相等的話比較第二位以此類推直到得出結果。
舉例:
1 | var buffer1 = Buffer.from('ABCDEF99'); |
上面那個buffer1
和buffer2
比較的話,result
的結果是1
,前面的結果都是相等,直到比較9>8
的時候出結果。按位逐一比較直到出結果。
如果把buffer1
設為12313213121
這種純數字呢,數字和字母比較的結果就是-1
。
1 | buffer.slice(); |
裁剪功能返回的實際是原始緩存區buffer
或者一部分,操作的是與原始buffer
同一塊內存區域。
1 | // 裁剪 |
輸出:
1 | $ node main.js |
可以看到對裁剪返回的buffer
進行寫操作同時,也對原始buffer
進行了寫操作。
註:以上參考了
Node.js Buffer(缓冲区)