簡單入門Buffer

若是你第一次認識buffer,你可能會很陌生,由於在前端的JavaScript中並無buffer,由於前端只要作一些字符串操做或DOM基本操做就能知足業務需求。前端

buffer是什麼?

buffer是Node底層經過C++申請的內存,經過JS來分配內存。也就是存放文件的緩衝區。那麼問題來了,爲何叫作緩存區,瞭解以前就要先跟你們科普一下V8的內存限制。數組

當咱們在代碼中聲明變量並賦值時,所使用對象的內存就分配在堆中。若是已申請的堆空閒內存不夠分配新的對象,將繼續申請堆內存,直到堆的大小超過V8的限制爲止。(64位系統下約爲1.4 GB,32位系統下約爲0.7 GB)緩存

那麼又爲何要限制,其實這樣設計是有目的,方便V8作垃圾回收,在作垃圾回收時JS是停滯的,等待垃圾回收完成再恢復,因此垃圾回收的耗時關係到咱們的性能,當內存太大就耗時越長,因此V8要這麼限制。bash

在這樣的限制下,將會致使Node沒法直接操做大內存對象,好比沒法將一個2 GB的文件讀入內存中進行字符串分析處理,那麼咱們就將文件讀取到buffer中,暫時存放,因此叫作緩衝區。性能

const fs = require('fs')

fs.readFile('./a.js', { encoding: 'utf8' }, (err, data) => {
  if (!err) {
    fs.writeFile('./b.js', data, { encoding: 'utf8' }, (err, data) => {
      if (err) {
        console.log('寫入失敗')
      }
    })
  } else {
    console.log('讀取失敗')
  }
})
複製代碼

不要使用fs.readFilesfs.writeFile直接進行大文件操做,而是使用 fs.createReadStreamfs.createWriteStream 方法經過流的方式實現對大文件的操做.ui

let reader = fs.createReadStream('a.js');
let writer = fs.createWriteStream('b.js');
reader.pipe(writer);
複製代碼

經過流的方式操做文件裏面的原理也就是使用了buffer做爲緩衝。每次讀一點寫一點。編碼

雖然buffer是申請的內存,不受V8內存的限制,可是物理內存依然是有限的。spa

瞭解Buffer

Buffer是一個像Array的對象,但它主要用於操做字節設計

因爲Buffer太過常見,Node在進程啓動時就已經加載了它,並將其放在全局對象(global)上。因此在使用Buffer時,無須經過 require() 便可直接使用。code

Buffer對象相似於數組,它的元素爲16進制的兩位數,即0到255的數值。

let buf = Buffer.from('hello', 'utf8')
console.log(buf)
// <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log(buf.length) // 5
console.log(buf[0]) // 104
複製代碼

能夠訪問 length 屬性獲得長度(表示的是字節的長度,在utf8編碼中漢字是3字節,英文是1字節),也能夠經過下標訪問元素。

關於下標訪問元素須要注意的是要經歷一個計算的過程。咱們經過獲取第一個字母爲例,首先是 h 根據ASCII碼對照表查出來16進制是68,而後經過JS中的toString方法傳入參數爲2表示轉換成二進制,獲得1101000,而後再換成10進制的數就變成了104,因此經過下標訪問的第一個元素結果是104,具體代碼以下。

let buf = Buffer.from('hello', 'utf8')
console.log(buf)
// <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log((0x68).toString(2))
// 1101000
複製代碼

Buffer.from 的用法在這裏介紹一下,第一個參數是字符串,表示建立一個包含字符串的buffer,第二個參數是指定字符的編碼,默認值也是utf8

相關文章
相關標籤/搜索