Node.js入门:Buffer对象学习

2023-11-05

前言

计算机底层存储的数据都是二进制的。在前端开发中一般都是实现页面效果,很少会直接操作二进制的数据。而在 Node.js 擅长的领域,比如在服务端程序开发中,经常会读取文件,处理文件,和二进制数据打交道比较多。

Buffer 对象是 Node.js 提供的一个全局对象,专门用来处理二进制数据

二进制数据在开发中,操作和表示都非常不方便,所以 Buffer 对象采用十六进制来表示二进制数据。比如二进制数据 00001111,转为十六进制就是 f。用 buffer 表示就是:

let buffer = Buffer.from([0b1111])
console.log(buffer)  // <Buffer 0f>

创建 buffer

Buffer 既然是一个对象,那么一般可以通过 new 的方式创建它的实例:

let buffer = new Buffer()

但是这种方式由于安全性已经废弃了。在实例化时会报错。

文档推荐使用这几种新的方法来创建:

  • Buffer.alloc:创建指定字节大小的 buffer。
  • Buffer.allocUnsafe:从名字看就知道是一个不安全的 API 。不推荐使用。
  • Buffer.from:使用传入的数据创建 buffer,最常用的方法。

Buffer.alloc

创建 buffer 的时候需要指定 buffer 的大小。

// 创建一个 3 字节大小的buffer
let buffer = Buffer.alloc(3)
console.log(buffer)

// buffer 使用十六进制来描述二进制数据,长这样:
// 由于没有往里存东西,所以都为 00
// <Buffer 00 00 00>

Buffer.allocUnsafe

let buffer = Buffer.allocUnsafe(3)
console.log(buffer) // 值不确定

为什么值不确定呢?

由于 V8 引擎的 GC 机制,会产生内存碎片,一块空间不再使用了,但是还没有被回收。此时就有可能会被这个方法拿来创建一个 buffer ,所以创建出来的 buffer 可能并不是空的。这就是为什么值不确定的原因。同样也是不推荐使用该方法的原因。
其实该方法也谈不上不安全,只是不干净而已,并不影响最终的使用,因为创建之后总会用新的数据覆盖它。

Buffer.from

该方法接收两个参数,第一个参数是用来创建 buffer 的数据,也就是要存到缓冲区的数据,有三种类型:字符串,数组和 Buffer 实例

第二个参数用来指定编码格式,默认为 utf-8

使用字符串创建 buffer
let buffer1 = Buffer.from('abc')
console.log(buffer1)  

// 默认使用 utf-8 编码,一个字符占一个字节,所以有三个字节大小
// <Buffer 61 62 63>


let buffer2 = Buffer.from('昆吾')
console.log(buffer2)  

// 默认使用 utf-8 编码,一个汉字占3个字节。所以所以生成的 buffer有6个字节
// <Buffer e6 98 86 e5 90 be>
使用数组创建 buffer

数组里可以放二进制,十进制,八进制,十六进制,字符串。

let buffer1 = Buffer.from([1, 2, 3])
let buffer2 = Buffer.from([0x4, 0x5, 0x6])
let buffer3 = Buffer.from([0b111, 0b1000, 0b1001])
console.log(buffer1)
console.log(buffer2)
console.log(buffer3)

/*
<Buffer 01 02 03>
<Buffer 04 05 06>
<Buffer 07 08 09>
*/
使用 buffer 创建 buffer
let buffer1 = Buffer.alloc(3)
let buffer2 = Buffer.from(buffer1)
console.log(buffer1)// <Buffer 00 00 00>
console.log(buffer2)// <Buffer 00 00 00>

创建出来的两个 buffer 长的一样,但是两块独立的内存空间,互不影响。

Buffer 的实例方法

观察上文中创建的 buffer,比如 <Buffer 01 02 03>,非常像是一个数组。

我们可以将 buffer 看作是一个存放二进制数据的数组,只不过每一项都是一字节大小的数据,而非我们熟悉的数字、字符串等。

Buffer 是一个全局对象,打印一下它的原型对象:

console.log(Buffer.prototype)

观察可知,它继承自 Uint8Array 对象,并且有非常多的原型方法。我们主要学习一些常用的,包括 copytoStringindexOfincludesfillwritesubarray 等。

toString

将从 buffer 中读取出来的数据转为字符串类型。

接收三个可选参数,分别是编码格式,从 buffer 中读取数据的起始位置。

let buffer = Buffer.from('昆吾kw')

console.log(buffer) // <Buffer e6 98 86 e5 90 be 6b 77>
console.log(buffer.toString()) // 昆吾kw    读取全部数据转为字符串
console.log(buffer.toString('utf8', 6)) // kw   从第7个字节开始读取 
console.log(buffer.toString('utf8', 0, 6)) // 昆吾  读取第1个到第6个字节

我们发现,buffer 在使用时和数组非常像,也可以通过从0开始的索引来指定位置,0索引表示的就是第一个字节。后面的示例中我们以此表示。

copy

把 buffer 中的数据拷贝到另一个 buffer 中。

接收四个参数,第一个为拷贝数据的目标 buffer,必填。第二个参数是目标 buffer 从哪个位置开始接收接收数据。后两个参数指定从源 buffer 中取数据的起始位置。

let target = Buffer.alloc(8)

let source = Buffer.from('昆吾kw')


// 部分拷贝。将 source 中 0-5 个字节也就是“昆吾” 拷贝至 target 中,target 从 0 位置开始接收
source.copy(target, 2, 0, 6)
console.log(target) // <Buffer 00 00 e6 98 86 e5 90 be>
console.log(target.toString()) // 昆吾

// 完整拷贝。将 source 中的数据拷贝到 target 中。
source.copy(target)
console.log(target.toString()) // 昆吾kw

indexOf

类似字符串和数组中的 indexOf 方法,用于查找目标中匹配到的第一个元素的位置。

在 buffer 中,就是找匹配到的字节的位置。

接收两个参数。第一个是要查找的内容,第二个指定从 buffer 的哪个字节开始查找。找到了则返回字节的位置,找不到返回 -1。

let buffer = Buffer.from('hello, world')

console.log(buffer) // <Buffer 68 65 6c 6c 6f 2c 20 77 6f 72 6c 64>

console.log(buffer.indexOf('l')) // 返回找到的第一个匹配的字节位置
console.log(buffer.indexOf('l', 3)) // 从 buffer 的第4个字节开始查找。
console.log(buffer.indexOf('a')) // -1 。 若找不到返回 -1

includes

判断 buffer 中是否包含指定的数据。类似于数组的 includes 方法。

接收两个参数。第一个是要查找的内容,第二个指定从 buffer 的哪个字节开始查找。若 buffer 中包含,则返回 true,不包含返回false。

let buffer = Buffer.from('hello, world')

console.log(buffer.includes('l')) // true
console.log(buffer.includes('a')) // false

includes 方法和 indexOf 方法的作用是一样的,都是用于查找一个目标数据。

fill

向 buffer 中填充数据。

接收4个参数,第一个是要填充进 buffer 的数据。第二、三个参数分别表示 buffer 接收数据的起始位置。第四个参数设置编码格式,默认为 utf8

let buffer = Buffer.alloc(8)

// 将 '123' 填充到 buffer 中,从第三个字节开始填充,直到填满
buffer.fill('123', 2)
console.log(buffer) // <Buffer 00 00 31 32 33 31 32 33>
console.log(buffer.toString())  // 123123

// 将 '123' 填充到 buffer 中,默认填满
buffer.fill('123')
console.log(buffer) // <Buffer 31 32 33 31 32 33 31 32>
console.log(buffer.toString()) // 12312312

write

向 buffer 中写入数据。

接收三个参数。第一个是写入的数据,第二、三个分别是 buffer 接收数据的起始位置。第四个参数设置编码格式,默认为 utf8

let buffer = Buffer.alloc(6)

// 将 '123' 写入到 buffer 中,数据有多少就写入多少
buffer.write('123')
console.log(buffer) // <Buffer 31 32 33 00 00 00>
console.log(buffer.toString()) // 123

// 将 '123' 填充到 buffer 中,从第三个字节开始填充,数据有多少写入多少
buffer.write('123', 3)
console.log(buffer) //<Buffer 31 32 33 31 32 33>
console.log(buffer.toString())  // 123123

writefill 的区别:前者是数据有多少往 buffer 中写入多少,而 fill 是重复写入,直到填满整个 buffer。

subarray

从 buffer 中截取数据并返回一个新的 buffer。

在数组和字符串的原型方法中,截取数据的方法叫作 slice。而 Buffer 对象中的 slice 方法已经废弃,改用 subarray

该方法接收4个参数,第一个是要填充进 buffer 的数据。第二、三个参数分别表示 buffer 接收数据的起始位置。第四个参数设置编码格式,默认为 utf8

let buffer = Buffer.from('123456')

// 截取 buffer 的全部数据
let subBuffer1 = buffer.subarray()

// 截取 buffer 的前三个字节
let subBuffer2 = buffer.subarray(0, 3)

console.log(buffer) // <Buffer 31 32 33 34 35 36>
console.log(subBuffer1) // <Buffer 31 32 33 34 35 36>
console.log(subBuffer2) // <Buffer 31 32 33>

Buffer 的静态方法

Buffer的静态方法我们已经学过三个了,就是用来创建 buffer 的 allocallocUnSafe from 方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DiWOJhEZ-1675356697098)(https://static.kunwu.tech/images/2022-08/202208020753371.webp)]

Buffer.concat

将多个 buffer 拼接成一个新的 buffer。就类似数组中的 concat 方法。用的非常多。

let buffer1 = Buffer.from('昆吾')
let buffer2 = Buffer.from('kw')

console.log(Buffer.concat([buffer1, buffer2]))

// 第二个参数指定生成新的 buffer 的长度
console.log(Buffer.concat([buffer1, buffer2], 7))

// <Buffer e6 98 86 e5 90 be 6b 77>
// <Buffer e6 98 86 e5 90 be 6b>

Buffer.isBuffer

这个很好理解,见名知义,用来判断数据是否是 buffer 类型。

let buffer = Buffer.from('1')

console.log(Buffer.isBuffer(1)) // false
console.log(Buffer.isBuffer(buffer)) // true

总结

本文简单介绍了 Node.js 中 Buffer 对象的使用,包括创建实例 buffer 的方法,以及操作 buffer 的常用方法。

创建 buffer 主要使用两个方法:

  • Buffer.alloc:创建一个固定字节大小的内存空间
  • Buffer.from:将传入的数据转为二进制放到内存中,用法有很多

操作 buffer 的方法包括 Buffer 原型对象上的实例方法和 Buffer 类的静态方法:

  • toString:读取 buffer 中的数据,转为字符串
  • copy:拷贝 buffer 中的数据到另一个 buffer 中
  • indexOf:查找 buffer 中是否有目标内容
  • includes:作用和 indexOf 相同,返回结果不同
  • fill:向 buffer 中填充数据
  • write:向 buffer 中写入数据
  • subarray:从 buffer 中截取数据
  • Buffer.concat:拼接 buffer
  • Buffer.isBufer:判断 buffer 类型

方法比较多,而且不常用,有印象即可。本文可作为文档使用,以供需要时翻看。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js入门:Buffer对象学习 的相关文章

随机推荐

  • chatgpt论文润色

    https github com binary husky chatgpt academic
  • 开源库nothings/stb的介绍及使用(图像方面)

    GitHub上有个开源的stb库 Star数已过万 地址为https github com nothings stb 为何叫stb 是用的作者名字的缩写Sean T Barrett 此库仅包含头文件 除stretchy buffer h外
  • 佛祖保佑 永不宕机 永无BUG C语言 串口打印

    字符串如下 char log oo0oo r n o8888888o r n 88 88 r n r n 0 0 r n r n r n
  • ChromeDriver最新版(116.x及最新)下载途径分享

    首先查看version 在地址栏输入chrome version 最新版 官方地址 https googlechromelabs github io chrome for testing 选择合适的下载即可 Old 官网 https chr
  • 关于postman使用技巧

    一 get方法 只在此显示下有token的查询方法 一般的get查询直接浏览器地址即可 二 post请求 1 在headers中设置下Content Type为application json 2 在Body中输入正确的json格式即可 三
  • 从零实现DevOps(二):Centos7操作系统-环境变量配置(JDK、Maven、Node)

    1 JDK安装并配置环境变量 由于Jenkins官网要求 从2 357版本后必须用java11或17才可以运行 java8运行会报错 所以我们直接安装jdk11 1 下载地址 往下拉可以找到Java11 Java Downloads Ora
  • C语言速成指南

    说明一下吧 这篇文章是用于c语言有目的的速成 有点基础的看一看也可以当复习 如果想要真正学好c语言 建议看一下之前写的详细教程 这篇文章会有很多对于考试没有多大帮助的东西被忽略掉 临近期末祝大家考试顺利 我也会不断完善这篇文章的 欢迎各路大
  • SQLMap 注入 DVWA实战

    一 low级别 1 进入dvwa界面输入1 点击Submit 得到链接 http localhost dvwa master vulnerabilities sqli id 1 Submit Submit 2 我们用sqlmap进行爆破 s
  • springboot 配置多个请求服务代理

    springboot 配置服务代理 有时候 我们可能有下边这样的需求 即 针对于分布式服务 我们会有多种业务接口服务 但是服务器上可能只要求开放一个服务的端口 比如上图的restA项目端口是对外开放的 但是restB项目端口并未对外开放 这
  • StringBuffer与StringBuilder的区别

    StringBuffer与StringBuilder的区别 一 String StringBuffer与StringBuilder String字符串常量 String的值是不可变的 这就导致每次对String的操作都会生成新的String
  • 运算符优先级

    C语言中 运算符除了常见的三大类 算术运算符 关系运算符与逻辑运算符之外 还有一些用于完成特殊任务的运算符 运算符的运算优先级共分为15 级 1 级最高 15 级最低 在表达式中 优先级较高的先于优先级较低的进行运算 而在一个运算量两侧的运
  • 我爱Java系列之《JavaEE学习笔记day12》---【缓冲流、转换流、序列/反序列化流、打印流】

    一 缓冲流 1 字节缓冲输出流java io BufferedOutputStream extends OutputStream 高效字节输出流 写入文件 目标文件 底层定义个了一个长度为8192的数组 提高效率 常用方法 write in
  • lvm扩容是否影响oracle,linux下对LVM扩容

    扩容原因 dev vg rhel64 lv root 占用率达到100 导致部分应用无法继续运行 操作过程 1 关闭系统 在虚拟机中添加一块10G的磁盘 2 查看新添加磁盘对应的名称 email protected fdisk cul 得知
  • 人工智能大语言模型微调技术:SFT 监督微调、LoRA 微调方法、P-tuning v2 微调方法、Freeze 监督微调方法

    1 SFT 监督微调 1 1 SFT 监督微调基本概念 SFT Supervised Fine Tuning 监督微调是指在源数据集上预训练一个神经网络模型 即源模型 然后创建一个新的神经网络模型 即目标模型 目标模型复制了源模型上除了输出
  • nodejs安装和环境配置-Windows

    0 安装过程中遇到的常见问题 访问 https blog csdn net weixin 52799373 article details 125718587 spm 1001 2014 3001 5502 1 下载node js 下载地址
  • 向数据库插入数据、修改数据时自动生成时间以及自动修改时间

    数据库中列名为 created 用于自动记录 数据添加 的时间 其数据类型为 timestamp 默认为 CURRENT TIMESTAMP 修改成功后 下次添加新的数据 该列会自动记录系统时间 CREATE TABLE example i
  • Keycloak 登录方案

    转自 Keycloak 13 自定义用户身份认证流程 User Storage SPI Zhang Xiang 博客园
  • 管理系统 -----sku

    目录 skuform静态页面 ui下拉框 reduce 方法详解及高级技巧 语法 reduce的简单用法 reduce的高级用法 项目实战应用 SKUFORM完整代码 完成查看SKU列表的loading效果 spu父组件 sku页面 深度选
  • 字节跳动面试分享,android内存优化面试题

    一 开发背景 想要成为一名优秀的Android开发 你需要一份完备的知识体系 在这里 让我们一起成长为自己所想的那样 我们的项目需要开发一款智能硬件 它由 Web 后台发送指令到一款桌面端应用程序 再由桌面程序来控制不同的硬件设备实现业务上
  • Node.js入门:Buffer对象学习

    前言 计算机底层存储的数据都是二进制的 在前端开发中一般都是实现页面效果 很少会直接操作二进制的数据 而在 Node js 擅长的领域 比如在服务端程序开发中 经常会读取文件 处理文件 和二进制数据打交道比较多 Buffer 对象是 Nod