教程(十七):Buffer(緩沖區(qū)))
一、什么是 BufferJavaScript 語(yǔ)言自身只有字符串?dāng)?shù)據(jù)類型沒(méi)有二進(jìn)制數(shù)據(jù)類型。Node.js 中的Buffer 類是用于處理二進(jìn)制數(shù)據(jù)的核心工具提供了對(duì)二進(jìn)制數(shù)據(jù)的高效操作。Buffer 類在處理文件操作、網(wǎng)絡(luò)通信、圖像處理等場(chǎng)景中特別有用。Buffer 的特性特性說(shuō)明二進(jìn)制數(shù)據(jù)Buffer 對(duì)象是一個(gè)包含原始二進(jìn)制數(shù)據(jù)的固定大小的數(shù)組每個(gè)元素占用一個(gè)字節(jié)8位適合處理文件內(nèi)容、網(wǎng)絡(luò)數(shù)據(jù)包等固定長(zhǎng)度Buffer 對(duì)象的內(nèi)容可以在創(chuàng)建后修改但其長(zhǎng)度是固定的不能動(dòng)態(tài)改變二、Buffer 與字符編碼Buffer 實(shí)例一般用于表示編碼字符的序列比如 UTF-8、UCS2、Base64 或十六進(jìn)制編碼的數(shù)據(jù)。通過(guò)使用顯式的字符編碼就可以在 Buffer 實(shí)例與普通的 JavaScript 字符串之間進(jìn)行相互轉(zhuǎn)換。const buf Buffer.from(runoob, ascii); // 輸出 72756e6f6f62 console.log(buf.toString(hex)); // 輸出 cnVub29i console.log(buf.toString(base64));Node.js 支持的字符編碼編碼說(shuō)明ascii僅支持 7 位 ASCII 數(shù)據(jù)速度很快utf8多字節(jié)編碼的 Unicode 字符許多網(wǎng)頁(yè)和文檔格式都使用 UTF-8utf16le2 或 4 個(gè)字節(jié)小字節(jié)序編碼的 Unicode 字符ucs2utf16le 的別名base64Base64 編碼latin1一種把 Buffer 編碼成一字節(jié)編碼的字符串方式binarylatin1 的別名hex將每個(gè)字節(jié)編碼為兩個(gè)十六進(jìn)制字符三、創(chuàng)建 BufferBuffer 提供了以下 API 來(lái)創(chuàng)建 Buffer 類方法說(shuō)明Buffer.alloc(size[, fill[, encoding]])創(chuàng)建長(zhǎng)度為 size 字節(jié)的 Buffer每個(gè)字節(jié)的值為 0推薦Buffer.allocUnsafe(size)創(chuàng)建長(zhǎng)度為 size 字節(jié)的 Buffer但可能包含舊數(shù)據(jù)更快但不安全Buffer.allocUnsafeSlow(size)分配給定大小的新 Buffer 實(shí)例但不對(duì)其進(jìn)行初始化Buffer.from(array)返回一個(gè)被 array 的值初始化的新的 Buffer 實(shí)例Buffer.from(arrayBuffer[, byteOffset[, length]])返回與給定 ArrayBuffer 共享同一內(nèi)存的 BufferBuffer.from(buffer)復(fù)制傳入的 Buffer 實(shí)例的數(shù)據(jù)返回新的 Buffer 實(shí)例Buffer.from(string[, encoding])通過(guò)字符串創(chuàng)建 Buffer可指定編碼默認(rèn)為 UTF-8創(chuàng)建示例// 創(chuàng)建一個(gè)長(zhǎng)度為 10、且用 0 填充的 Buffer const buf1 Buffer.alloc(10); // 創(chuàng)建一個(gè)長(zhǎng)度為 10、且用 0x1 填充的 Buffer const buf2 Buffer.alloc(10, 1); // 創(chuàng)建一個(gè)長(zhǎng)度為 10、且未初始化的 Buffer // 這個(gè)方法比 Buffer.alloc() 更快但可能包含舊數(shù)據(jù) const buf3 Buffer.allocUnsafe(10); // 創(chuàng)建一個(gè)包含 [0x1, 0x2, 0x3] 的 Buffer const buf4 Buffer.from([1, 2, 3]); // 創(chuàng)建一個(gè)包含 UTF-8 字節(jié)的 Buffer const buf5 Buffer.from(tést); // 創(chuàng)建一個(gè)包含 Latin-1 字節(jié)的 Buffer const buf6 Buffer.from(tést, latin1);四、寫(xiě)入緩沖區(qū)語(yǔ)法buf.write(string[, offset[, length]][, encoding])參數(shù)參數(shù)說(shuō)明string寫(xiě)入緩沖區(qū)的字符串offset緩沖區(qū)開(kāi)始寫(xiě)入的索引值默認(rèn)為 0length寫(xiě)入的字節(jié)數(shù)默認(rèn)為buffer.lengthencoding使用的編碼默認(rèn)為 utf8返回值返回實(shí)際寫(xiě)入的大小。如果 buffer 空間不足則只會(huì)寫(xiě)入部分字符串。示例buf Buffer.alloc(256); len buf.write(www.runoob.com); console.log(寫(xiě)入字節(jié)數(shù) : len);執(zhí)行以上代碼輸出結(jié)果為$ node main.js 寫(xiě)入字節(jié)數(shù) : 14五、從緩沖區(qū)讀取數(shù)據(jù)語(yǔ)法buf.toString([encoding[, start[, end]]])參數(shù)參數(shù)說(shuō)明encoding使用的編碼默認(rèn)為 utf8start指定開(kāi)始讀取的索引位置默認(rèn)為 0end結(jié)束位置默認(rèn)為緩沖區(qū)的末尾返回值解碼緩沖區(qū)數(shù)據(jù)并使用指定的編碼返回字符串。示例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, 0, 5)); // 輸出: abcde console.log(buf.toString(utf8, 0, 5)); // 輸出: abcde console.log(buf.toString(undefined, 0, 5)); // 輸出: abcde六、將 Buffer 轉(zhuǎn)換為 JSON 對(duì)象語(yǔ)法buf.toJSON()當(dāng)字符串化一個(gè) Buffer 實(shí)例時(shí)JSON.stringify()會(huì)隱式地調(diào)用該toJSON()方法。示例const buf Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json JSON.stringify(buf); // 輸出: {type:Buffer,data:[1,2,3,4,5]} console.log(json); const copy JSON.parse(json, (key, value) { return value value.type Buffer ? Buffer.from(value.data) : value; }); // 輸出: Buffer 01 02 03 04 05 console.log(copy);七、緩沖區(qū)合并語(yǔ)法Buffer.concat(list[, totalLength])參數(shù)參數(shù)說(shuō)明list用于合并的 Buffer 對(duì)象數(shù)組列表totalLength指定合并后 Buffer 對(duì)象的總長(zhǎng)度返回值返回一個(gè)多個(gè)成員合并的新 Buffer 對(duì)象。示例var buffer1 Buffer.from(教程); var buffer2 Buffer.from(www.runoob.com); var buffer3 Buffer.concat([buffer1, buffer2]); console.log(buffer3 內(nèi)容: buffer3.toString());執(zhí)行以上代碼輸出結(jié)果為buffer3 內(nèi)容: 教程www.chenbyte.cn八、緩沖區(qū)比較語(yǔ)法buf.compare(otherBuffer);參數(shù)參數(shù)說(shuō)明otherBuffer與 buf 對(duì)象比較的另外一個(gè) Buffer 對(duì)象返回值返回一個(gè)數(shù)字表示buf在otherBuffer之前、之后或相同。示例var buffer1 Buffer.from(ABC); var buffer2 Buffer.from(ABCD); var result buffer1.compare(buffer2); if (result 0) { console.log(buffer1 在 buffer2 之前); } else if (result 0) { console.log(buffer1 與 buffer2 相同); } else { console.log(buffer1 在 buffer2 之后); }執(zhí)行以上代碼輸出結(jié)果為ABC在ABCD之前九、拷貝緩沖區(qū)語(yǔ)法buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])參數(shù)參數(shù)說(shuō)明targetBuffer要拷貝的 Buffer 對(duì)象targetStart可選默認(rèn): 0sourceStart可選默認(rèn): 0sourceEnd可選默認(rèn):buffer.length返回值沒(méi)有返回值。示例var buf1 Buffer.from(abcdefghijkl); var buf2 Buffer.from(RUNOOB); // 將 buf2 插入到 buf1 指定位置上 buf2.copy(buf1, 2); console.log(buf1.toString());執(zhí)行以上代碼輸出結(jié)果為abRUNOOBijkl十、緩沖區(qū)裁剪語(yǔ)法buf.slice([start[, end]])參數(shù)參數(shù)說(shuō)明start可選默認(rèn): 0end可選默認(rèn):buffer.length返回值返回一個(gè)新的緩沖區(qū)它和舊緩沖區(qū)指向同一塊內(nèi)存但是從索引start到end的位置剪切。示例var buffer1 Buffer.from(runoob); // 剪切緩沖區(qū) var buffer2 buffer1.slice(0, 2); console.log(buffer2 content: buffer2.toString());執(zhí)行以上代碼輸出結(jié)果為buffer2 content: ru十一、緩沖區(qū)長(zhǎng)度語(yǔ)法buf.length;返回值返回 Buffer 對(duì)象所占據(jù)的內(nèi)存長(zhǎng)度。示例var buffer Buffer.from(www.runoob.com); // 緩沖區(qū)長(zhǎng)度 console.log(buffer length: buffer.length);執(zhí)行以上代碼輸出結(jié)果為buffer length: 14十二、Buffer 常用方法參考序號(hào)方法 描述1Buffer.from()- 從字符串、數(shù)組或 Buffer 創(chuàng)建 Buffer推薦2buf.length- 返回 buffer 的字節(jié)數(shù)3buf.write(string[, offset[, length]][, encoding])- 寫(xiě)入數(shù)據(jù)到 buffer4buf.toString([encoding[, start[, end]]])- 從 buffer 讀取數(shù)據(jù)5buf.toJSON()- 將 Buffer 實(shí)例轉(zhuǎn)換為 JSON 對(duì)象6buf.equals(otherBuffer)- 比較兩個(gè)緩沖區(qū)是否相等7buf.compare(otherBuffer)- 比較兩個(gè) Buffer 對(duì)象8buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])- 拷貝緩沖區(qū)9buf.slice([start[, end]])- 裁剪緩沖區(qū)共享內(nèi)存10Buffer.concat(list[, totalLength])- 合并緩沖區(qū)11buf.fill(value[, offset][, end])- 用指定值填充緩沖區(qū)12buf.readUInt8(offset[, noAssert])- 讀取無(wú)符號(hào) 8 位整數(shù)13buf.readUInt16LE(offset[, noAssert])- 讀取無(wú)符號(hào) 16 位整數(shù)小端14buf.readUInt16BE(offset[, noAssert])- 讀取無(wú)符號(hào) 16 位整數(shù)大端15buf.readUInt32LE(offset[, noAssert])- 讀取無(wú)符號(hào) 32 位整數(shù)小端16buf.readUInt32BE(offset[, noAssert])- 讀取無(wú)符號(hào) 32 位整數(shù)大端17buf.readInt8(offset[, noAssert])- 讀取有符號(hào) 8 位整數(shù)18buf.readInt16LE(offset[, noAssert])- 讀取有符號(hào) 16 位整數(shù)小端19buf.readInt16BE(offset[, noAssert])- 讀取有符號(hào) 16 位整數(shù)大端20buf.readInt32LE(offset[, noAssert])- 讀取有符號(hào) 32 位整數(shù)小端21buf.readInt32BE(offset[, noAssert])- 讀取有符號(hào) 32 位整數(shù)大端22buf.readFloatLE(offset[, noAssert])- 讀取 32 位浮點(diǎn)數(shù)小端23buf.readFloatBE(offset[, noAssert])- 讀取 32 位浮點(diǎn)數(shù)大端24buf.readDoubleLE(offset[, noAssert])- 讀取 64 位雙精度數(shù)小端25buf.readDoubleBE(offset[, noAssert])- 讀取 64 位雙精度數(shù)大端26buf.writeUInt8(value, offset[, noAssert])- 寫(xiě)入無(wú)符號(hào) 8 位整數(shù)27buf.writeUInt16LE(value, offset[, noAssert])- 寫(xiě)入無(wú)符號(hào) 16 位整數(shù)小端28buf.writeUInt16BE(value, offset[, noAssert])- 寫(xiě)入無(wú)符號(hào) 16 位整數(shù)大端29buf.writeUInt32LE(value, offset[, noAssert])- 寫(xiě)入無(wú)符號(hào) 32 位整數(shù)小端30buf.writeUInt32BE(value, offset[, noAssert])- 寫(xiě)入無(wú)符號(hào) 32 位整數(shù)大端31buf.writeInt8(value, offset[, noAssert])- 寫(xiě)入有符號(hào) 8 位整數(shù)32buf.writeInt16LE(value, offset[, noAssert])- 寫(xiě)入有符號(hào) 16 位整數(shù)小端33buf.writeInt16BE(value, offset[, noAssert])- 寫(xiě)入有符號(hào) 16 位整數(shù)大端34buf.writeInt32LE(value, offset[, noAssert])- 寫(xiě)入有符號(hào) 32 位整數(shù)小端35buf.writeInt32BE(value, offset[, noAssert])- 寫(xiě)入有符號(hào) 32 位整數(shù)大端36buf.writeFloatLE(value, offset[, noAssert])- 寫(xiě)入 32 位浮點(diǎn)數(shù)小端37buf.writeFloatBE(value, offset[, noAssert])- 寫(xiě)入 32 位浮點(diǎn)數(shù)大端38buf.writeDoubleLE(value, offset[, noAssert])- 寫(xiě)入 64 位雙精度數(shù)小端39buf.writeDoubleBE(value, offset[, noAssert])- 寫(xiě)入 64 位雙精度數(shù)大端十三、本章小結(jié)知識(shí)點(diǎn)說(shuō)明Buffer 是什么Node.js 中處理二進(jìn)制數(shù)據(jù)的核心工具創(chuàng)建 Buffer推薦使用Buffer.from()、Buffer.alloc()寫(xiě)入數(shù)據(jù)buf.write()將字符串寫(xiě)入緩沖區(qū)讀取數(shù)據(jù)buf.toString()從緩沖區(qū)讀取字符串合并與復(fù)制Buffer.concat()合并buf.copy()復(fù)制裁剪buf.slice()裁剪共享內(nèi)存注意修改影響原 Buffer長(zhǎng)度buf.length獲取緩沖區(qū)字節(jié)數(shù)JSON 轉(zhuǎn)換buf.toJSON()轉(zhuǎn)換為 JSON 對(duì)象編碼支持UTF-8、ASCII、Base64、Hex 等多種編碼提示Buffer.allocUnsafe()雖然更快但可能包含舊數(shù)據(jù)使用前需要填充或覆蓋。推薦在大多數(shù)場(chǎng)景下使用Buffer.alloc()或Buffer.from()以確保安全。