詳解Nodejs Buffer模組的常用API

青灯夜游
發布: 2021-05-21 09:30:46
轉載
1795 人瀏覽過

本篇文章帶大家詳細介紹一下NodejsBuffer模組的常用API。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

詳解Nodejs Buffer模組的常用API

模組概覽

Buffer是node的核心模組,開發者可以利用它來處理二進位數據,例如文件流的讀寫、網路請求資料的處理等。

Buffer的API非常多,本文只挑選 比較常用/容易理解 的API進行講解,包括Buffer實例的創建、比較、連接、拷貝、查找、遍歷、類型轉換、截取、編碼轉換等。 【推薦學習:《nodejs 教程》】

建立

  • #new Buffer(array)
  • ##Buffer. alloc(length)
  • Buffer.allocUnsafe(length)
  • Buffer.from(array)

透過new Buffer(array)
// Creates a new Buffer containing the ASCII bytes of the string 'buffer' const buf = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
登入後複製

驗證下:

var array = 'buffer'.split('').map(function(v){ return '0x' + v.charCodeAt(0).toString(16) }); console.log( array.join() ); // 输出:0x62,0x75,0x66,0x66,0x65,0x72
登入後複製

透過Buffer.alloc(length)
var buf1 = Buffer.alloc(10); // 长度为10的buffer,初始值为0x0 var buf2 = Buffer.alloc(10, 1); // 长度为10的buffer,初始值为0x1
登入後複製
var buf3 = Buffer.allocUnsafe(10); // 长度为10的buffer,初始值不确定
登入後複製
var buf4 = Buffer.from([1, 2, 3]) // 长度为3的buffer,初始值为 0x01, 0x02, 0x03
登入後複製

透過Buffer.from()

#例子一:Buffer.from(array)

// [0x62, 0x75, 0x66, 0x66, 0x65, 0x72] 为字符串 "buffer" // 0x62 为16进制,转成十进制就是 98,代表的就是字母 b var buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); console.log(buf.toString());
登入後複製

例子二:Buffer.from(string[, encoding])

透過string建立buffer,跟著將buffer轉成字符字串時,記得編碼保持一致,不然會出現亂碼,如下圖。

var buf = Buffer.from('this is a tést'); // 默认采用utf8 // 输出:this is a tést console.log(buf.toString()); // 默认编码是utf8,所以正常打印 // 输出:this is a tC)st console.log(buf.toString('ascii')); // 转成字符串时,编码不是utf8,所以乱码
登入後複製

對亂碼的分析如下:

var letter = 'é'; var buff = Buffer.from(letter); // 默认编码是utf8,这里占据两个字节  var len = buff.length; // 2 var code = buff[0]; // 第一个字节为0xc3,即195:超出ascii的最大支持范围 var binary = code.toString(2); // 195的二进制:10101001 var finalBinary = binary.slice(1); // 将高位的1舍弃,变成:0101001 var finalCode = parseInt(finalBinary, 2); // 0101001 对应的十进制:67 var finalLetter = String.fromCharCode(finalCode); // 67对应的字符:C // 同理 0xa9最终转成的ascii字符为) // 所以,最终输出为 this is a tC)st
登入後複製

例子三:Buffer.from(buffer)

建立新的Buffer實例,並將buffer的資料拷貝到新的實例子中去。

var buff = Buffer.from('buffer'); var buff2 = Buffer.from(buff); console.log(buff.toString()); // 输出:buffer console.log(buff2.toString()); // 输出:buffer buff2[0] = 0x61; console.log(buff.toString()); // 输出:buffer console.log(buff2.toString()); // 输出:auffer
登入後複製

buffer比較

buf.equals(otherBuffer)

判斷兩個buffer實例儲存的資料是否相同,如果是,回傳true,否則回傳false。

// 例子一:编码一样,内容相同 var buf1 = Buffer.from('A'); var buf2 = Buffer.from('A'); console.log( buf1.equals(buf2) ); // true // 例子二:编码一样,内容不同 var buf3 = Buffer.from('A'); var buf4 = Buffer.from('B'); console.log( buf3.equals(buf4) ); // false // 例子三:编码不一样,内容相同 var buf5 = Buffer.from('ABC'); //  var buf6 = Buffer.from('414243', 'hex'); console.log(buf5.equals(buf6)); //true //只要比较的两者内容相同,`buf.equals(otherBuffer)` 就返回true
登入後複製

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])##同樣是對兩個buffer實例進行比較,不同的是:

    可以指定特定比較的範圍(透過start、end指定)
  • 傳回值為整數,達標buf、 target的大小關係
  • 假設傳回值為

    0
  • :buf、target大小相同。
  • 1
  • :buf大於target,也就是說buf應該排在target之後。
  • -1
  • :buf小於target,也就是說buf應該排在target之前。
  • 看例子,官方的例子還蠻好的,直接貼一下:
const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('BCD'); const buf3 = Buffer.from('ABCD'); // Prints: 0 console.log(buf1.compare(buf1)); // Prints: -1 console.log(buf1.compare(buf2)); // Prints: -1 console.log(buf1.compare(buf3)); // Prints: 1 console.log(buf2.compare(buf1)); // Prints: 1 console.log(buf2.compare(buf3)); // Prints: [ , ,  ] // (This result is equal to: [buf1, buf3, buf2]) console.log([buf1, buf2, buf3].sort(Buffer.compare));
登入後複製

Buffer.compare(buf1, buf2)

buf.compare(target)

大同小異,一般用於排序。直接貼官方例子:

const buf1 = Buffer.from(&#39;1234&#39;); const buf2 = Buffer.from(&#39;0123&#39;); const arr = [buf1, buf2]; // Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ] // (This result is equal to: [buf2, buf1]) console.log(arr.sort(Buffer.compare));
登入後複製

從Buffer.from([62])談起

這裡稍微研究下Buffer.from(array)。下面是官方文件對API的說明,也就是說,每個array的元素對應1個位元組(8位元),取值從0到255。

Allocates a new Buffer using an array of octets.

陣列元素為數字

首先看下,傳入的元素為數字的場景。以下分別是10進制、8進制、16進制,跟預期中的結果一致。

var buff = Buffer.from([62]) //  // buff[0] === parseInt('3e', 16) === 62
登入後複製
var buff = Buffer.from([062]) //  // buff[0] === parseInt(62, 8) === parseInt(32, 16) === 50
登入後複製
var buff = Buffer.from([0x62]) //  // buff[0] === parseInt(62, 16) === 98
登入後複製

陣列元素為字串

再看下,傳入的元素為字串的場景。

  • 0

    開頭的字串,在parseInt('062')時,可以解釋為62,也可以解釋為50(八進位),這裡看到採用了第一種解釋。

  • 字串的場景,跟parseInt()有沒有關係,暫未深入探究,只是這樣猜想。 TODO(找時間研究下)
  • var buff = Buffer.from(['62']) //  // buff[0] === parseInt('3e', 16) === parseInt('62') === 62
    登入後複製
    var buff = Buffer.from(['062']) //  // buff[0] === parseInt('3e', 16) === parseInt('062') === 62
    登入後複製
    var buff = Buffer.from(['0x62']) //  // buff[0] === parseInt('62', 16) === parseInt('0x62') === 98
    登入後複製
陣列元素大小超出1個位元組

有興趣的同學自行探究。

var buff = Buffer.from([256]) // 
登入後複製

Buffer.from('1')

一開始不自覺的會將

Buffer.from('1')[0]

"1"劃等號,其實"1"對應的編碼是49。

var buff = Buffer.from(&#39;1&#39;) // <Buffer 31> console.log(buff[0] === 1) // false
登入後複製
這樣對比就知道了,編碼為1的是個控製字符,表示 Start of Heading。

console.log( String.fromCharCode(49) ) // '1' console.log( String.fromCharCode(1) ) // '\u0001'
登入後複製

buffer連結:Buffer.concat(list[, totalLength])

備註:個人覺得

totalLength

這個參數挺多餘的,從官方文檔來看,是處於效能提升的角度考量。不過內部實作也只是遍歷list,將length累加得到totalLength,從這點來看,效能最佳化是幾乎可以忽略不計的。

var buff1 = Buffer.alloc(10); var buff2 = Buffer.alloc(20); var totalLength = buff1.length + buff2.length; console.log(totalLength); // 30 var buff3 = Buffer.concat([buff1, buff2], totalLength); console.log(buff3.length); // 30
登入後複製
除了上述的效能最佳化,totalLength還有兩點要注意。假設list裡面所有buffer的長度累加和為length

  • totalLength > length:返回长度为totalLength的Buffer实例,超出长度的部分填充0。
  • totalLength < length:返回长度为totalLength的Buffer实例,后面部分舍弃。
var buff4 = Buffer.from([1, 2]); var buff5 = Buffer.from([3, 4]); var buff6 = Buffer.concat([buff4, buff5], 5); console.log(buff6.length); // console.log(buff6); //  var buff7 = Buffer.concat([buff4, buff5], 3); console.log(buff7.length); // 3 console.log(buff7); // 
登入後複製

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

使用比较简单,如果忽略后面三个参数,那就是将buf的数据拷贝到target里去,如下所示:

var buff1 = Buffer.from([1, 2]); var buff2 = Buffer.alloc(2); buff1.copy(buff2); console.log(buff2); // 
登入後複製

另外三个参数比较直观,直接看官方例子

const buf1 = Buffer.allocUnsafe(26); const buf2 = Buffer.allocUnsafe(26).fill('!'); for (let i = 0 ; i < 26 ; i++) { // 97 is the decimal ASCII value for 'a' buf1[i] = i + 97; } buf1.copy(buf2, 8, 16, 20); // Prints: !!!!!!!!qrst!!!!!!!!!!!!! console.log(buf2.toString('ascii', 0, 25));
登入後複製

查找:buf.indexOf(value[, byteOffset][, encoding])

跟数组的查找差不多,需要注意的是,value可能是String、Buffer、Integer中的任意类型。

  • String:如果是字符串,那么encoding就是其对应的编码,默认是utf8。
  • Buffer:如果是Buffer实例,那么会将value中的完整数据,跟buf进行对比。
  • Integer:如果是数字,那么value会被当做无符号的8位整数,取值范围是0到255。

另外,可以通过byteOffset来指定起始查找位置。

直接上代码,官方例子妥妥的,耐心看完它基本就理解得差不多了。

const buf = Buffer.from('this is a buffer'); // Prints: 0 console.log(buf.indexOf('this')); // Prints: 2 console.log(buf.indexOf('is')); // Prints: 8 console.log(buf.indexOf(Buffer.from('a buffer'))); // Prints: 8 // (97 is the decimal ASCII value for 'a') console.log(buf.indexOf(97)); // Prints: -1 console.log(buf.indexOf(Buffer.from('a buffer example'))); // Prints: 8 console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8))); const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); // Prints: 4 console.log(utf16Buffer.indexOf('\u03a3', 0, 'ucs2')); // Prints: 6 console.log(utf16Buffer.indexOf('\u03a3', -4, 'ucs2'));
登入後複製

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

将sring写入buf实例,同时返回写入的字节数。

参数如下:

  • string:写入的字符串。
  • offset:从buf的第几位开始写入,默认是0。
  • length:写入多少个字节,默认是 buf.length - offset。
  • encoding:字符串的编码,默认是utf8。

看个简单例子

var buff = Buffer.alloc(4); buff.write('a'); // 返回 1 console.log(buff); // 打印  buff.write('ab'); // 返回 2 console.log(buff); // 打印 
登入後複製

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

value填充buf,常用于初始化buf。参数说明如下:

  • value:用来填充的内容,可以是Buffer、String或Integer。
  • offset:从第几位开始填充,默认是0。
  • end:停止填充的位置,默认是 buf.length。
  • encoding:如果value是String,那么为value的编码,默认是utf8。

例子:

var buff = Buffer.alloc(20).fill('a'); console.log(buff.toString()); // aaaaaaaaaaaaaaaaaaaa
登入後複製

转成字符串: buf.toString([encoding[, start[, end]]])

把buf解码成字符串,用法比较直观,看例子

var buff = Buffer.from('hello'); console.log( buff.toString() ); // hello console.log( buff.toString('utf8', 0, 2) ); // he
登入後複製

转成JSON字符串:buf.toJSON()

var buff = Buffer.from('hello'); console.log( buff.toJSON() ); // { type: 'Buffer', data: [ 104, 101, 108, 108, 111 ] }
登入後複製

遍历:buf.values()、buf.keys()、buf.entries()

用于对buf进行for...of遍历,直接看例子。

var buff = Buffer.from('abcde'); for(const key of buff.keys()){ console.log('key is %d', key); } // key is 0 // key is 1 // key is 2 // key is 3 // key is 4 for(const value of buff.values()){ console.log('value is %d', value); } // value is 97 // value is 98 // value is 99 // value is 100 // value is 101 for(const pair of buff.entries()){ console.log('buff[%d] === %d', pair[0], pair[1]); } // buff[0] === 97 // buff[1] === 98 // buff[2] === 99 // buff[3] === 100 // buff[4] === 101
登入後複製

截取:buf.slice([start[, end]])

用于截取buf,并返回一个新的Buffer实例。需要注意的是,这里返回的Buffer实例,指向的仍然是buf的内存地址,所以对新Buffer实例的修改,也会影响到buf。

var buff1 = Buffer.from('abcde'); console.log(buff1); //  var buff2 = buff1.slice(); console.log(buff2); //  var buff3 = buff1.slice(1, 3); console.log(buff3); //  buff3[0] = 97; // parseInt(61, 16) ==> 97 console.log(buff1); // 
登入後複製

TODO

  • 创建、拷贝、截取、转换、查找

  • buffer、arraybuffer、dataview、typedarray

  • buffer vs 编码

  • Buffer.from()、Buffer.alloc()、Buffer.alocUnsafe()

  • Buffer vs TypedArray

文档摘要

关于buffer内存空间的动态分配

Instances of the Buffer class are similar to arrays of integers but correspond to fixed-sized, raw memory allocations outside the V8 heap. The size of the Buffer is established when it is created and cannot be resized.

相关链接

unicode对照表 https://unicode-table.com/cn/#control-character

字符编码笔记:ASCII,Unicode和UTF-8 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

更多编程相关知识,请访问:编程视频!!

以上是詳解Nodejs Buffer模組的常用API的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!