NodeAPI學習之Buffer

luckyzv發表於2019-02-16

Buffer

可以在TCP流或者檔案系統操作等場景中處理二進位制資料流。

Buffer例項類似於整數陣列,但是Buffer大小固定、且在V8堆外分配實體記憶體,Buffer的大小在建立時確定,無法調整。

常用Buffer類方法

注意:(以下方法Node新版本中已被廢棄,不建議使用

不建議使用的有如下:newBuffer(array)newBuffer(arrayBuffer)newBuffer(buffer)newBuffer(size)newBuffer(string)

替代方法有如下:Buffer.from()Buffer.alloc()Buffer.allocUnsafe()

  • Buffer.from(array)返回一個新建的包含所提供的位元組陣列的副本的Buffer。
let buf1 = Buffer.from([1,2,3,4]) // <Buffer 01 02 03 04>
let buf2 = Buffer.from([[0x62, 0x75, 0x66, 0x66, 0x65, 0x72]]) // <Buffer 62 75 66 66 65 72>
buf2.toString() // `buffer`
  • Buffer.from(arrayBuffer[,byteOffset[,length]])返回一個新建的與給定的ArrayBuffer共享同一記憶體的Buffer。
const arr = new Unit16Array(2)

const buf = Buffer.from(arr.buffer) // 改動arr也會影響到buf
  • Buffer.from(buffer)返回一個新建的包含所提供的Buffer的內容的副本的Buffer。
let buf1 = Buffer.from(`buffer`)
let buf2 = Buffer.from(buf1)
buf1[0] = 0x61
console.log(buf1) // auffer
console.log(buf2) // buffer
  • Buffer.from(string[,encoding])返回一個新建的包含所提供的字串的副本的Buffer。
  • Buffer.alloc(size[,fill[,encoding]])返回一個指定大小的被填滿的Buffer例項。這個方法會明顯地比Buffer.allocUnsafe(size)慢,但可確保新建立的Buffer例項絕不會包含舊的和潛在的敏感資料。
// size: 新建的Buffer期望的長度
// fill:<string | Buffer | integer>用來預填充新建的Buffer的值,預設:0
// encoding:如果fill是字串,那麼這個就是字元編碼,預設:utf-8

const buf = Buffer.alloc(5) // <Buffer 00 00 00 00 00>
const buf = Buffer.alloc(5, `a`) // <Buffer 61 61 61 61 61>
const buf = Buffer.alloc(11, `aGVsbG8gd29ybGQ=`, `base64`) // 輸出: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64> hello world
  • Buffer.allocUnsafe(size)Buffer.allocUnsafeSlow(size)返回一個新建的指定size的Buffer,但它的內容必須被初始化,可以使用buf.fill(0)或完全寫滿。

開發者應該把所有正在使用的newBuffer()建構函式遷移到新的API上。

是什麼造成了Buffer.allocUnsafe()Buffer.allocUnsafeSlow()不安全?

是因為呼叫這兩個方法時,被分配的記憶體都是未被初始化的(未被0填充),雖然這樣的設計使得記憶體的分配非常快(效能優勢),但是已經分配的記憶體段可能包含潛在的敏感舊資料。使用通過Buffer.allocUnsafe()建立的沒有被完全重寫記憶體的Buffer,在Buffer記憶體可讀的情況下,有可能洩露它的舊資料。

Buffer與字元編碼

通過指定的編碼進位制,可以在Buffer與普通的字串之間轉換。目前支援的asciiutf-8base-64binaryhex

const buf = Buffer.from(`helloworld`, `ascii`)
buf.toString(`hex`)
buf.toString(`base64`)

BufferES6迭代器

同樣,Buffer例項可以使用迭代器for…of進行遍歷,遍歷器的buf.values()buf.keys()、buf.entries()可以用於建立迭代器。

const buf = Buffer.from([1, 2, 3])
for(let b of buf){
    console.log(b) // 1 2 3
}

類方法

  • Buffer.byteLength(string[, encoding])返回一個字串的實際位元組長度。String.prototype.length是返回字串的字元數

注意字元數和位元組長度是不同,英文字母中是相同的,但是當有中文時或者unicode編碼(它是用兩個位元組來編碼一個字元)是不同的。

`中文hello`.length // 7
Buffer.byteLength(`中文hello`, `uft-8`) // 11
  • Buffer.compare(buf1, buf2)通常用於Buffer例項陣列的排序。(有點像sort()方法)
  • Buffer.concat(list[, totalLength])合併Buffer
const buf1 = Buffer.alloc(10)
const buf2 = Buffer.alloc(14)
const buf3 = Buffer.alloc(18)
const totalLength = buf1.length + buf2.length + buf3.length // 42

const bufA = Buffer.concat([buf1, buf2, buf3], 41) // 截斷為totalLength的長度,缺少的部分會用00補充

cosnole.log(buf.length) // 41
  • Buffer.isBuffer(obj),是一個buffer返回true
  • Buffer.isEncoding(encoding),是一個支援的字元編碼返回true
  • Buffer.entries(),建立並返回一個[index, byte]形式的迭代器
cosnt buf = Buffer.from(`buffer`)

for(let pair of buf.entries()) {
    console.log(pair) // [0, 98],[1, 117]...
}
  • buf.equals(otherBuffer),如果buf與otherBuffer具有完全相同的位元組就返回true

相關文章