buffer是什么?下面本篇文章帶大家深入了解一下Nodejs中的buffer模塊,介紹一下創(chuàng)建、復制、拼接、截取、填充Buffer,以及Buffer與String相互轉換的方法,希望對大家有所幫助!
1.buffer是什么?
我們知道,JS在對字符串、數(shù)組、數(shù)字、布爾值等都有對應的方法API進行操作處理,而在Node中,還需要文件操作、網絡通信、操作數(shù)據(jù)庫、數(shù)據(jù)傳輸?shù)饶芰?;文件在存儲層面都是以二進制形式表示,在http的請求和響應中數(shù)據(jù)的傳輸也是以二進制數(shù)據(jù)進行傳輸,所以僅僅目前的JS能力還是不夠的,也就在Node中提供了buffer模塊。
即:使得NodeJS擁有像操作字符串一樣來操作處理二進制數(shù)據(jù)的能力。buffer也被稱為臨時性暫存區(qū)
,即臨時存放輸入和輸出二進制數(shù)據(jù)的一段內存。
在之前的一篇文章聊聊Nodejs中的核心模塊:stream流模塊(看看如何使用)中,我們了解到在對大文件進行讀取操作時候,一般不會一次性全部讀取到內存中,而是以流的形式讀取一段數(shù)據(jù)塊,而連續(xù)的數(shù)據(jù)塊便形成了數(shù)據(jù)流的概念。而在對數(shù)據(jù)塊讀取和寫入過程中,數(shù)據(jù)首先會存儲在buffer(臨時性暫存區(qū))
的內存中,以待被處理。
1.1 了解buffer內存分配
buffer對象的內存分配并不是在V8的堆內存中,而是在Node的C++層面實現(xiàn)內存的申請;為了高效的使用申請來得內存,Node中采用slab分配機制(一種動態(tài)內存管理機制)。
1. 2 buffer的全局性
Node在進程啟動時buffer就已經加裝進入內存,并將其放入全局對象,使用時候可以無需require引入,但是官方但仍然建議通過 import 或 require 語句顯式地引用它。
2. 創(chuàng)建Buffer
buffer實例除了可以在文件讀取,http請求得到之外,還可以通過手動方式構造創(chuàng)建。
2.1 Buffer.alloc(size[, fill[, encoding]])
參數(shù):
- size: buffer長度
- fill: 預填充值,默認值:0
- encoding: 如果fill是字符串,則就是字符串的編碼,默認:utf-8
import { Buffer } from 'buffer'; const buf = Buffer.alloc(8); console.log(buf); // <Buffer 00 00 00 00 00 00 00 00>
2.2 Buffer.allocUnsafe(size)
參數(shù):
- size: 新的buffer所需要長度
- 以這種方式創(chuàng)建的 Buffer 實例的底層內存不會被初始化。 新創(chuàng)建的 Buffer 的內容是未知的,可能包含敏感的數(shù)據(jù)。
import { Buffer } from 'buffer'; const buf = Buffer.allocUnsafe(8); console.log(buf); // <Buffer e8 bf 99 e6 98 af e4 b8 80 e6>
2.3 Buffer.from(string[, encoding])
創(chuàng)建包含傳入string的新buffer
參數(shù):
- string: 字符串
- encoding: 編碼,默認值:utf-8
import { Buffer } from 'buffer'; const buf = Buffer.from('hello buffer'); console.log(buf); // <Buffer 68 65 6c 6c 6f 20 62 75 66 66 65 72>
2.4 Buffer.from(array)
使用 0
– 255
范圍內的字節(jié) array
分配新的 Buffer
。
import { Buffer } from 'buffer'; const array = [0x62, 0x78, 0x84]; const buf = Buffer.from(array); console.log(buf); // <Buffer 62 78 84>
3. 復制Buffer
3.1 Buffer.from(buffer)
參數(shù):
- buffer,要復制的buffer實例
import { Buffer } from 'buffer'; // 新建 const buf1 = Buffer.alloc(10, 2); // 復制 const buf2 = Buffer.from(buf1); console.log(buf1); // <Buffer 02 02 02 02 02 02 02 02 02 02> console.log(buf2); // <Buffer 02 02 02 02 02 02 02 02 02 02>
3.2 buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
將buf實例復制到target目標
import { Buffer } from 'buffer'; const buf1 = Buffer.alloc(10, 2); const buf2 = Buffer.allocUnsafe(10) // 將buf1復制到buf2 buf1.copy(buf2); console.log(buf1); // <Buffer 02 02 02 02 02 02 02 02 02 02> console.log(buf2); // <Buffer 02 02 02 02 02 02 02 02 02 02>
4. 拼接Buffer
4.1 Buffer.concat(list[, totalLength])
返回list中所有buffer實例連接在一起的新buffer
參數(shù):
- list:<Buffer[]> | <Unit8Array[]>
- totalLength: 連接總長度。
注意
:
- 如果列表沒有條目,或者 totalLength 為 0,則返回新的零長度 Buffer。
- 如果未提供 totalLength,則從 list 中的 Buffer 實例通過相加其長度來計算。
import { Buffer } from 'buffer'; const buf1 = Buffer.alloc(4, 2); const buf2 = Buffer.alloc(4, 3); const buf3 = Buffer.concat([buf1, buf2]); console.log(buf1); // <Buffer 02 02 02 02> console.log(buf2); // <Buffer 03 03 03 03> console.log(buf3); // <Buffer 02 02 02 02 03 03 03 03>
5. 截取Buffer
5.1 buf.slice([start[, end]])
從buf實例中返回新的Buffer實例,返回的新Buffer實例只是源buf實例的引用,即對新返回的實例修改會影響原有的Buffer實例
參數(shù):
- start: 起始位置,默認0
- end: 結束位置,默認buf.length
import { Buffer } from 'buffer'; const buf1 = Buffer.alloc(10, 2); // 截取 const buf2 = buf1.slice(1,4); // 截取部分修改 buf2[0] = 0x63; console.log(buf1); // <Buffer 02 63 02 02 02 02 02 02 02 02> console.log(buf2); // <Buffer 63 02 02>
6. 填充Buffer
6.1 buf.fill(value[, offset[, end]][, encoding])
參數(shù):
- value,填充值
- offset: 在開始填充 buf 之前要跳過的字節(jié)數(shù),默認值0
- end: 結束填充buf(不包括在內)的位置,默認值buf.length
- encoding,如果value值為字符串,則為字符串編碼,默認utf-8
import { Buffer } from 'buffer'; const buf1 = Buffer.allocUnsafe(8).fill(2); console.log(buf1); // <Buffer 02 02 02 02 02 02 02 02>
6.2 buf.write(string[, offset[, length]][, encoding])
根據(jù) encoding 中的字符編碼將 string 寫入 buf 的 offset 處。
注意
:length 參數(shù)是要寫入的字節(jié)數(shù)。 如果 buf 沒有足夠的空間來容納整個字符串,則只會寫入 string 的一部分
參數(shù):
- string: 寫入的字符串值
- offset: 開始寫入 string 之前要跳過的字節(jié)數(shù),默認值為0
- length: 寫入的最大字節(jié)數(shù),默認值buf.length – offset
- encoding: 編碼,默認utf-8
import { Buffer } from 'buffer'; // buf1 length為12 const buf1 = Buffer.alloc(12, 3); // write offset大于buf1.length,寫入無效 buf1.write('hello', 12); console.log(buf1); // <Buffer 03 03 03 03 03 03 03 03 03 03 03 03> // 部分寫入 buf1.write('hello', 10); // <Buffer 03 03 03 03 03 03 03 03 03 03 68 65>
7. Buffer工具方法
7.1 Buffer.isBuffer(obj)
檢驗傳入obj是否為buffer
import { Buffer } from 'buffer'; const buf1 = Buffer.alloc(12, 3); console.log(Buffer.isBuffer(buf1)); // true
7.2 Buffer.isEncoding(encoding)
檢查傳入的編碼名稱是否被Buffer所支持
import { Buffer } from 'buffer'; console.log(Buffer.isEncoding('utf-8')) // true
8. Buffer與String的轉換
Buffer轉String
8.1 buf.toString([encoding[, start[, end]]])
參數(shù):
- encoding:使用的字符串編碼,默認utf-8
- start,開始位置,默認0
- end,結束位置,默認buf.length
import { Buffer } from 'buffer'; const buf1 = Buffer.allocUnsafe(26) for (let i = 0; i < 26; i++) { // 97 是 'a' 的十進制 ASCII 值。 buf1[i] = i + 97; } console.log(buf1.toString()) // abcdefghijklmnopqrstuvwxyz
String轉Buffer
8.2 Buffer.from(string[, encoding])
參數(shù):
- string: 字符串
- encoding: 編碼,默認值:utf-8
import { Buffer } from 'buffer'; const buf = Buffer.from('hello buffer'); console.log(buf); // <Buffer 68 65 6c 6c 6f 20 62 75 66 66 65 72>
9. Buffer與Array的對比
9.1 與Array類似點
- 可以使用下標獲取指定位置的值
- 可以使用length屬性獲取Buffer大小
- 可以使用for…of遍歷
9.2 與Array不同之處
- 存儲的是16進制的兩位數(shù)
- 值為0-255
- 支持多種編碼格式
- 內存不在v8堆中分配
- 底層有c++實現(xiàn),上層由js控制