1. 程式人生 > 程式設計 >node.JS二進位制操作模組buffer物件使用方法詳解

node.JS二進位制操作模組buffer物件使用方法詳解

在ES6引入TypedArray之前,JavaScript語言沒有讀取或操作二進位制資料流的機制。Buffer類被引入作為Nodejs的API的一部分,使其可以在TCP流和檔案系統操作等場景中處理二進位制資料流。現在TypedArray已經被新增進ES6中,Buffer類以一種更優與更適合Node.js用例的方式實現了Uint8Array。

Buffer物件概述

由於應用場景不同,在Node中,應用需要處理網路協議、操作資料庫、處理圖片、接收上傳檔案等,在網路流和檔案的操作中,還要處理大量二進位制資料,JavaScript自有的字串遠遠不能滿足這些需求,於是Buffer物件應運而生

Buffer是一個典型的JavaScript與C++結合的模組,它將效能相關部分用C++實現,將非效能相關的部分用JavaScript實現。Buffer類的例項類似於整數陣列,除了其是大小固定的、且在V8堆外分配實體記憶體。Buffer的大小在其建立時就已確定,且不能調整大小

由於Buffer太過常見,Node在程序啟動時就已經載入了它,並將其放在全域性物件(global)上。所以在使用Buffer時,無須通過require()即可直接使用

/*
{ [Function: Buffer]
 poolSize: 8192,from: [Function],alloc: [Function],allocUnsafe: [Function],allocUnsafeSlow: [Function],isBuffer: [Function: isBuffer],compare: [Function: compare],isEncoding: [Function],concat: [Function],byteLength: [Function: byteLength] }
 */
console.log(Buffer);

建立Buffer物件

在 Node.js v6之前的版本中,Buffer例項是通過Buffer建構函式建立的,它根據提供的引數返回不同的 Buffer,而新版本的nodejs則提供了對應的方法

1、new Buffer(size)。傳一個數值作為第一個引數給Buffer()(如new Buffer(10)),則分配一個指定大小的新建的Buffer物件

分配給這種Buffer例項的記憶體是未初始化的(沒有用0填充)。雖然這樣的設計使得記憶體的分配非常快,但已分配的記憶體段可能包含潛在的敏感舊資料

這種Buffer例項必須手動地被初始化,可以使用buf.fill(0)或寫滿這個Buffer。雖然這種行為是為了提高效能而有意為之的,但開發經驗表明,建立一個快速但未初始化的Buffer與建立一個慢點但更安全的Buffer之間需要有更明確的區分

var buf = new Buffer(5);
console.log(buf);//<Buffer e0 f7 1d 01 00>
buf.fill(0);
console.log(buf);//<Buffer 00 00 00 00 00>

[注意]當我們為一個Buffer物件分配空間大小後,其長度就是固定的,不能更改

var buf = new Buffer(5);
console.log(buf);//<Buffer b8 36 70 01 02>
buf[0] = 1;
console.log(buf);//<Buffer 01 36 70 01 02>
buf[10] = 1;
console.log(buf);//<Buffer 01 79 43 6f 6e>

Buffer.allocUnsafe(size)

 在新版本中,由Buffer.allocUnsafe(size)方法替代,來分配一個大小為 size 位元組的新建的沒有用0填充的Buffer。可以使用buf.fill(0)初始化Buffer例項為0

var buf = Buffer.allocUnsafe(10);
console.log(buf);//<Buffer 75 63 74 42 79 4c 65 6e 67 74>
buf.fill(0);
console.log(buf);//<Buffer 00 00 00 00 00 00 00 00 00 00>

Buffer.alloc(size[,fill[,encoding]])

在新版本中,使用Buffer.alloc(size)方法可以生成一個安全的buffer物件,引數size <Integer> 新建的 Buffer 期望的長度;fill <String> | <Buffer> | <Integer> 用來預填充新建的 Buffer 的值。 預設: 0;encoding <String> 如果 fill 是字串,則該值是它的字元編碼。 預設: 'utf8'

分配一個大小為 size 位元組的新建的 Buffer 。 如果 fill 為 undefined ,則該 Buffer 會用 0 填充

var buf = Buffer.alloc(5);

console.log(buf);//<Buffer 00 00 00 00 00>

2、new Buffer(array或buffer)。傳一個數組或Buffer作為第一個引數,則將所傳物件的資料拷貝到Buffer 

var buf1 = new Buffer([1,2,3,4,5]);
console.log(buf1);//<Buffer 01 02 03 04 05>
var buf2 = new Buffer(buf1);
console.log(buf2);//<Buffer 01 02 03 04 05>

Buffer.from(array或buffer)

 在新版本中,由Buffer.from(array或buffer)方法替代

var buf1 = Buffer.from([1,5]);
console.log(buf1);//<Buffer 01 02 03 04 05>
var buf2 = Buffer.from(buf1);
console.log(buf2);//<Buffer 01 02 03 04 05>

3、new Buffer(string[,encoding])。第一個引數是字串,第二個引數是編碼方式,預設是'utf-8'

var buf1 = new Buffer('this is a tést');
console.log(buf1.toString());//this is a tést
console.log(buf1.toString('ascii'));//this is a tC)st
var buf2 = new Buffer('7468697320697320612074c3a97374','hex');
console.log(buf2.toString());//this is a tést

Node.js 目前支援的字元編碼包括:

'ascii' - 僅支援 7 位 ASCII 資料。如果設定去掉高位的話,這種編碼是非常快的。

'utf8' - 多位元組編碼的 Unicode 字元。許多網頁和其他文件格式都使用 UTF-8 。

'utf16le' - 2 或 4 個位元組,小位元組序編碼的 Unicode 字元。支援代理對(U+10000 至 U+10FFFF)。

'ucs2' - 'utf16le' 的別名。

'base64' - Base64 編碼。當從字串建立 Buffer 時,這種編碼可接受“URL 與檔名安全字母表”。

'latin1' - 一種把 Buffer 編碼成一位元組編碼的字串的方式。

'binary' - 'latin1' 的別名。

'hex' - 將每個位元組編碼為兩個十六進位制字元。

Buffer.from(string[,encoding])

在新版本中,由Buffer.from(string[,encoding]方法替代

var buf1 = Buffer.from('this is a tést');
console.log(buf1.toString());//this is a tést
console.log(buf1.toString('ascii'));//this is a tC)st
var buf2 = Buffer.from('7468697320697320612074c3a97374','hex');
console.log(buf2.toString());//this is a tést

4、new Buffer(arrayBuffer[,byteOffset [,length]])。引數arrayBuffer <ArrayBuffer> 一個 ArrayBuffer,或一個 TypedArray 的 .buffer 屬性;byteOffset <Integer> 開始拷貝的索引。預設為 0;length <Integer> 拷貝的位元組數。預設為 arrayBuffer.length - byteOffset

var arr = new Uint16Array(2);
arr[0] = 5000;
arr[1] = 4000;
var buf = new Buffer(arr.buffer);
console.log(buf);//<Buffer 88 13 a0 0f>
arr[1] = 6000;
console.log(buf);//<Buffer 88 13 70 17>

Buffer.from(arrayBuffer[,length]])

在新版本中,由Buffer.from(arrayBuffer[,length]])方法替代

var arr = new Uint16Array(2);
arr[0] = 5000;
arr[1] = 4000;
var buf = Buffer.from(arr.buffer);
console.log(buf);//<Buffer 88 13 a0 0f>
arr[1] = 6000;
console.log(buf);//<Buffer 88 13 70 17>

 

Buffer物件類似於陣列,它的元素為16進位制的兩位數,即0到255的數值

console.log(Buffer.from('test'));//<Buffer 74 65 73 74>

長度

不同編碼的字串佔用的元素個數各不相同,中文字在UTF-8編碼下佔用3個元素,字母和半形標點符號佔用1個元素

var buf = Buffer.from('match');

console.log(buf.length);//5

var buf = Buffer.from('火柴');

console.log(buf.length);//6

下標

Buffer受Array型別的影響很大,可以訪問length屬性得到長度,也可以通過下標訪問元素

var buf = Buffer.alloc(10); 

console.log(buf.length); // => 10

上述程式碼分配了一個長10位元組的Buffer物件。我們可以通過下標對它進行賦值

buf[0] = 100;

console.log(buf[0]); // => 100

要注意的是,給元素的賦值如果小於0,就將該值逐次加256,直到得到一個0到255之間的整數。如果得到的數值大於255,就逐次減256,直到得到0~255區間內的數值。如果是小數,捨棄小數部分,只保留整數部分

buf[0] = -100;

console.log(buf[0]); // 156

buf[1] = 300;

console.log(buf[1]); // 44

buf[2] = 3.1415;

console.log(buf[2]); // 3

fromcharcode

通常地,建立的buffer物件的內容是其uft-8字元編碼

var buf = Buffer.from('match'); 

console.log(buf); //<Buffer 6d 61 74 63 68>

如果要訪問其對應的字元,則需要使用字串的fromCharCode()方法

console.log(String.fromCharCode(buf[0]));//'m'

記憶體分配

Buffer物件的記憶體分配不是在V8的堆記憶體中,而是在Node的C++層面實現記憶體的申請的。因為處理大量的位元組資料不能採用需要一點記憶體就向作業系統申請一點記憶體的方式,這可能造成大量的記憶體申請的系統呼叫,對作業系統有一定壓力。為此Node在記憶體的使用上應用的是在C++層面申請記憶體、在JavaScript中分配記憶體的策略

為了高效地使用申請來的記憶體,Node採用了slab分配機制。slab是一種動態記憶體管理機制,最早誕生於SunOS作業系統(Solaris)中,目前在一些*nix作業系統中有廣泛的應用,如FreeBSD和Linux。簡單而言,slab就是一塊申請好的固定大小的記憶體區域。slab具有如下3種狀態:full:完全分配狀態;partial:部分分配狀態;empty:沒有被分配狀態

當我們需要一個Buffer物件,可以通過以下方式分配指定大小的Buffer物件:

new Buffer(size);//舊

Buffer.alloc(size);//新

poolSize

poolSize屬性是用於決定預分配的、內部 Buffer 例項池的大小的位元組數。預設地,Node以8KB為界限來區分Buffer是大物件還是小物件:

Buffer.poolSize = 8 * 1024;

這個8KB的值也就是每個slab的大小值,在JavaScript層面,以它作為單位單元進行記憶體的分配

1、分配小Buffer物件

如果指定Buffer的大小少於8KB,Node會按照小物件的方式進行分配。Buffer的分配過程中主要使用一個區域性變數pool作為中間處理物件,處於分配狀態的slab單元都指向它。以下是分配一個全新的slab單元的操作,它會將新申請的SlowBuffer物件指向它:

var pool;
function allocPool() {
  pool = new SlowBuffer(Buffer.poolSize);
  pool.used = 0;
}

構造小Buffer物件時的程式碼如下:

new Buffer(1024);//舊
Buffer.alloc(1024);//新

這次構造將會去檢查pool物件,如果pool沒有被建立,將會建立一個新的slab單元指向它:

if (!pool || pool.length - pool.used < this.length) allocPool();

同時當前Buffer物件的parent屬性指向該slab,並記錄下是從這個slab的哪個位置(offset)開始使用的,slab物件自身也記錄被使用了多少位元組,程式碼如下:

this.parent = pool; 
this.offset = pool.used; 
pool.used += this.length;
if (pool.used & 7) pool.used = (pool.used + 8) & ~7;

這時候的slab狀態為partial。當再次建立一個Buffer物件時,構造過程中將會判斷這個slab的剩餘空間是否足夠。如果足夠,使用剩餘空間,並更新slab的分配狀態。下面的程式碼建立了一個新的Buffer物件,它會引起一次slab分配:

new Buffer(3000);//舊

Buffer.alloc(3000);//新

如果slab剩餘的空間不夠,將會構造新的slab,原slab中剩餘的空間會造成浪費。例如,第一次構造1位元組的Buffer物件,第二次構造8192位元組的Buffer物件,由於第二次分配時slab中的空間不夠,所以建立並使用新的slab,第一個slab的8KB將會被第一個1位元組的Buffer物件獨佔。下面的程式碼一共使用了兩個slab單元:

new Buffer(1);//舊

Buffer.alloc(1);//新

new Buffer(8192);//舊

Buffer.alloc(8192);//新

要注意的是,由於同一個slab可能分配給多個Buffer物件使用,只有這些小Buffer物件在作用域釋放並都可以回收時,slab的8KB空間才會被回收。儘管建立了1個位元組的Buffer物件,但是如果不釋放它,實際可能是8KB的記憶體沒有釋放

2、分配大Buffer物件

如果需要超過8KB的Buffer物件,將會直接分配一個SlowBuffer物件作為slab單元,這個slab單元將會被這個大Buffer物件獨佔

// Big buffer,just alloc one

this.parent = new SlowBuffer(this.length); 

this.offset = 0;

這裡的SlowBuffer類是在C++中定義的,雖然引用buffer模組可以訪問到它,但是不推薦直接操作它,而是用Buffer替代

上面提到的Buffer物件都是JavaScript層面的,能夠被V8的垃圾回收標記回收。但是其內部的parent屬性指向的SlowBuffer物件卻來自於Node自身C++中的定義,是C++層面上的Buffer物件,所用記憶體不在V8的堆中

綜上,真正的記憶體是在Node的C++層面提供的,JavaScript層面只是使用它。當進行小而頻繁的Buffer操作時,採用slab的機制進行預先申請和事後分配,使得JavaScript到作業系統之間不必有過多的記憶體申請方面的系統呼叫。對於大塊的Buffer而言,則直接使用C++層面提供的記憶體,而無需細膩的分配操作

轉換

Buffer物件可以與字串之間相互轉換。目前支援的字串編碼型別有如下幾種:ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex

write()

一個Buffer物件可以儲存不同編碼型別的字串轉碼的值,呼叫write()方法可以實現該目的

buf.write(string,[offset],[length],[encoding])

string <String> 要寫入 buf 的字串

offset <Integer> 開始寫入 string 的位置。預設: 0

length <Integer> 要寫入的位元組數。預設: buf.length - offset

encoding <String> string 的字元編碼。預設: 'utf8';返回: <Integer> 寫入的位元組數

根據 encoding 的字元編碼寫入 string 到 buf 中的 offset 位置。 length 引數是寫入的位元組數。 如果 buf 沒有足夠的空間儲存整個字串,則只會寫入 string 的一部分。 只部分解碼的字元不會被寫入

var buf = Buffer.alloc(5); 

console.log(buf); //<Buffer 00 00 00 00 00>

var len = buf.write('test',1,3);

console.log(buf);//<Buffer 00 74 65 73 00>

console.log(len);/3

由於可以不斷寫入內容到Buffer物件中,並且每次寫入可以指定編碼,所以Buffer物件中可以存在多種編碼轉化後的內容。需要小心的是,每種編碼所用的位元組長度不同,將Buffer反轉回字串時需要謹慎處理

toString()

實現Buffer向字串的轉換也十分簡單,Buffer物件的toString()可以將Buffer物件轉換為字串

buf.toString([encoding],[start],[end])

encoding - 使用的編碼。預設為 'utf8'

start - 指定開始讀取的索引位置,預設為 0

end - 結束位置,預設為緩衝區的末尾

返回 - 解碼緩衝區資料並使用指定的編碼返回字串

var buf =Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {
 buf[i] = i + 97;
}
console.log( buf.toString('ascii'));//abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',5));//abcde
console.log( buf.toString('utf8',5));//abcde
console.log( buf.toString(undefined,5));//abcde

toJSON()

將 Node Buffer 轉換為 JSON 物件

buf.toJSON()

返回 buf 的 JSON 格式

var buf = Buffer.from('test');
var json = buf.toJSON(buf);
console.log(json);//{ type: 'Buffer',data: [ 116,101,115,116 ] }

isEncoding()

目前比較遺憾的是,Node的Buffer物件支援的編碼型別有限,只有少數的幾種編碼型別可以在字串和Buffer之間轉換。為此,Buffer提供了一個isEncoding()函式來判斷編碼是否支援轉換

Buffer.isEncoding(encoding)

將編碼型別作為引數傳入上面的函式,如果支援轉換返回值為true,否則為false。很遺憾的是,在中國常用的GBK、GB2312和BIG-5編碼都不在支援的行列中

console.log(Buffer.isEncoding('utf8'));//true

console.log(Buffer.isEncoding('gbk'));//false

Buffer類方法

Buffer.byteLength(string[,encoding])

Buffer.byteLength()方法返回一個字串的實際位元組長度。 這與 String.prototype.length 不同,因為那返回字串的字元數

string <String> | <Buffer> | <TypedArray> | <DataView> | <ArrayBuffer> 要計算長度的值

encoding <String> 如果 string 是字串,則這是它的字元編碼。 預設: 'utf8'

返回: <Integer> string 包含的位元組數

var str = '火柴';

var buf = Buffer.from(str);

console.log(str.length);//2

console.log(buf.length);//6

console.log(buf.byteLength);//6

Buffer.compare(buf1,buf2)

該方法用於比較 buf1 和 buf2 ,通常用於 Buffer 例項陣列的排序。 相當於呼叫 buf1.compare(buf2) 

buf1 <Buffer>

buf2 <Buffer>

Returns: <Integer>

var buf1 = Buffer.from('1234');

var buf2 = Buffer.from('0123');

var arr = [buf1,buf2];

var result = Buffer.compare(buf1,buf2);

console.log(result);//1

console.log(arr.sort());//[ <Buffer 30 31 32 33>,<Buffer 31 32 33 34> ]

Buffer.concat(list[,totalLength])

該方法返回一個合併了 list 中所有 Buffer 例項的新建的 Buffer

list <Array> 要合併的 Buffer 例項的陣列

totalLength <Integer> 合併時 list 中 Buffer 例項的總長度

返回: <Buffer>

如果 list 中沒有元素、或 totalLength 為 0 ,則返回一個新建的長度為 0 的 Buffer 。如果沒有提供 totalLength ,則從 list 中的 Buffer 例項計算得到。 為了計算 totalLength 會導致需要執行額外的迴圈,所以提供明確的長度會執行更快

var buf1 = Buffer.alloc(10);

var buf2 = Buffer.alloc(14);

var buf3 = Buffer.alloc(18);

var totalLength = buf1.length + buf2.length + buf3.length;

console.log(totalLength);//42

var bufA = Buffer.concat([buf1,buf2,buf3],totalLength); 

console.log(bufA);//<Buffer 00 00 00 00 ...>

console.log(bufA.length);//42

Buffer.isBuffer(obj)

如果 obj 是一個 Buffer 則返回 true ,否則返回 false

var buf = Buffer.alloc(5);
var str = 'test';
console.log(Buffer.isBuffer(buf));//true
console.log(Buffer.isBuffer(str));//false

例項方法

buf.slice([start[,end]])

該方法返回一個指向相同原始記憶體的新建的 Buffer,但做了偏移且通過 start 和 end 索引進行裁剪

start <Integer> 新建的 Buffer 開始的位置。 預設: 0

end <Integer> 新建的 Buffer 結束的位置(不包含)。 預設: buf.length

返回: <Buffer>

var buffer1 =Buffer.from('test');
console.log(buffer1);//<Buffer 74 65 73 74>
var buffer2 = buffer1.slice(1,3);
console.log(buffer2);//<Buffer 65 73>
console.log(buffer2.toString());//'es'

[注意]修改這個新建的 Buffer 切片,也會同時修改原始的 Buffer 的記憶體,因為這兩個物件所分配的記憶體是重疊的

var buffer1 =Buffer.from('test');
console.log(buffer1);//<Buffer 74 65 73 74>
var buffer2 = buffer1.slice(1,3);
console.log(buffer2);//<Buffer 65 73>
buffer2[0] = 0;
console.log(buffer1);//<Buffer 74 00 73 74>
console.log(buffer2);//<Buffer 00 73>

buf.copy(target[,targetStart[,sourceStart[,sourceEnd]]])

該方法用於拷貝 buf 的一個區域的資料到 target 的一個區域,即便 target 的記憶體區域與 buf 的重疊

target <Buffer> | <Uint8Array> 要拷貝進的 Buffer 或 Uint8Array

targetStart <Integer> target 中開始拷貝進的偏移量。 預設: 0

sourceStart <Integer> buf 中開始拷貝的偏移量。 當 targetStart 為 undefined 時忽略。 預設: 0

sourceEnd <Integer> buf 中結束拷貝的偏移量(不包含)。 當 sourceStart 為 undefined 時忽略。 預設: buf.length

返回: <Integer> 被拷貝的位元組數

var buffer1 =Buffer.from('test');
var buffer2 = Buffer.alloc(5);
var len = buffer1.copy(buffer2,3);
console.log(buffer1);//<Buffer 74 65 73 74>
console.log(buffer2);//<Buffer 00 74 00 00 00>
console.log(len);//1

buf.compare(target[,targetEnd[,sourceEnd]]]])

該方法比較 buf 與 target,返回表明 buf 在排序上是否排在 target 之前、或之後、或相同。 對比是基於各自 Buffer 實際的位元組序列

target <Buffer> 要比較的 Buffer

targetStart <Integer> target 中開始對比的偏移量。 預設: 0

targetEnd <Integer> target 中結束對比的偏移量(不包含)。 當 targetStart 為 undefined 時忽略。 預設: target.length

sourceStart <Integer> buf 中開始對比的偏移量。 當 targetStart 為 undefined 時忽略。 預設: 0

sourceEnd <Integer> buf 中結束對比的偏移量(不包含)。 當 targetStart 為 undefined 時忽略。 預設: buf.length

返回: <Integer>

如果 target 與 buf 相同,則返回 0 

如果 target 排在 buf 前面,則返回 1 

如果 target 排在 buf 後面,則返回 -1 

var buf1 = Buffer.from([1,5,6,7,8,9]);
var buf2 = Buffer.from([5,9,4]);
// 輸出: 0(buf2中的1234對比buf2中的1234)
console.log(buf1.compare(buf2,4));
// 輸出: -1(buf2中的567891對比buf1中的56789)
console.log(buf1.compare(buf2,4));
// 輸出: 1(buf2中的1對比buf2中的6789)
console.log(buf1.compare(buf2,5));

buf.equals(otherBuffer)

如果 buf 與 otherBuffer 具有完全相同的位元組,則返回 true,否則返回 false

otherBuffer <Buffer> 要比較的 Buffer

返回: <Boolean>

var buf1 = Buffer.from('ABC');
var buf2 = Buffer.from('ABC');
var buf3 = Buffer.from('abc');
console.log(buf1.equals(buf2));//true
console.log(buf1.equals(buf3));//false

buf.fill(value[,offset[,end]][,encoding])

value <String> | <Buffer> | <Integer> 用來填充 buf 的值

offset <Integer> 開始填充 buf 的位置。預設: 0

end <Integer> 結束填充 buf 的位置(不包含)。預設: buf.length

encoding <String> 如果 value 是一個字串,則這是它的字元編碼。 預設: 'utf8'

返回: <Buffer> buf 的引用

如果未指定 offset 和 end,則填充整個 buf。 這個簡化使得一個Buffer的建立與填充可以在一行內完成

var b = Buffer.allocUnsafe(10).fill('h');
console.log(b.toString());//hhhhhhhhhh

buf.indexOf(value[,byteOffset][,encoding])

value <String> | <Buffer> | <Integer> 要搜尋的值

byteOffset <Integer> buf 中開始搜尋的位置。預設: 0

encoding <String> 如果 value 是一個字串,則這是它的字元編碼。 預設: 'utf8'

返回: <Integer> buf 中 value 首次出現的索引,如果 buf 沒包含 value 則返回 -1

如果value是字串,則 value 根據 encoding 的字元編碼進行解析;如果value是Buffer,則value會被作為一個整體使用。如果要比較部分 Buffer 可使用 buf.slice();如果value是數值,則 value 會解析為一個 0 至 255 之間的無符號八位整數值

var buf = Buffer.from('this is a buffer');
// 輸出: 0
console.log(buf.indexOf('this'));
// 輸出: 2
console.log(buf.indexOf('is'));
// 輸出: 8
console.log(buf.indexOf(Buffer.from('a buffer')));
// 輸出: 8
// (97 是 'a' 的十進位制 ASCII 值)
console.log(buf.indexOf(97));
// 輸出: -1
console.log(buf.indexOf(Buffer.from('a buffer example')));
// 輸出: 8
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0,8)));

buf.lastIndexOf(value[,encoding])

與 buf.indexOf() 類似,除了 buf 是從後往前搜尋而不是從前往後

var buf = Buffer.from('this buffer is a buffer');
// 輸出: 0
console.log(buf.lastIndexOf('this'));
// 輸出: 17
console.log(buf.lastIndexOf('buffer'));
// 輸出: 17
console.log(buf.lastIndexOf(Buffer.from('buffer')));
// 輸出: 15
// (97 是 'a' 的十進位制 ASCII 值)
console.log(buf.lastIndexOf(97));
// 輸出: -1
console.log(buf.lastIndexOf(Buffer.from('yolo')));
// 輸出: 5
console.log(buf.lastIndexOf('buffer',5));
// 輸出: -1
console.log(buf.lastIndexOf('buffer',4));

buf.includes(value[,encoding])

該方法相當於 buf.indexOf() !== -1

value <String> | <Buffer> | <Integer> 要搜尋的值

byteOffset <Integer> buf 中開始搜尋的位置。預設: 0

encoding <String> 如果 value 是一個字串,則這是它的字元編碼。 預設: 'utf8'

返回: <Boolean> 如果 buf 找到 value,則返回 true,否則返回 false

var buf = Buffer.from('this is a buffer');
// 輸出: true
console.log(buf.includes('this'));
// 輸出: true
console.log(buf.includes('is'));
// 輸出: true
console.log(buf.includes(Buffer.from('a buffer')));
// 輸出: true
// (97 是 'a' 的十進位制 ASCII 值)
console.log(buf.includes(97));
// 輸出: false
console.log(buf.includes(Buffer.from('a buffer example')));
// 輸出: true
console.log(buf.includes(Buffer.from('a buffer example').slice(0,8)));
// 輸出: false

更多關於nodeJS二進位制操作模組buffer物件使用方法請檢視下面的相關連結