0

0

详解Nodejs Buffer模块的常用API

青灯夜游

青灯夜游

发布时间:2021-05-13 10:49:59

|

2137人浏览过

|

来源于掘金社区

转载

本篇文章带大家详细介绍一下nodejs buffer模块的常用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('1234');
const buf2 = Buffer.from('0123');
const arr = [buf1, buf2];

// Prints: [ ,  ]
// (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('1')  // 
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
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

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

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

4

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

7

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

42

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

4

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

3

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

3

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

2

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
快速入门Node.JS全套完整版
快速入门Node.JS全套完整版

共83课时 | 8.1万人学习

nodejs开发基础教程
nodejs开发基础教程

共15课时 | 4.5万人学习

JavaScript设计模式视频教程
JavaScript设计模式视频教程

共28课时 | 5.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号