文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

深入了解Node中的Buffer

2023-05-14 23:12

关注

最开始的时候 JS 只在浏览器端运行,对于 Unicode 编码的字符串容易处理,但是对于二进制和非 Unicode 编码的字符串处理困难。并且二进制是计算机最底层的数据格式,视频/音频/程序/网络包都是以二进制来存储的。所以 Node 需要引入一个对象来操作二进制,因此 Buffer 诞生了,用于 TCP流/文件系统等操作处理二进制字节。

由于 Buffer 在 Node 中过于常用,所以在 Node 启动的时候已经引入了 Buffer,无需使用 require()

ArrayBuffer

是什么

ArrayBuffer 是内存之中的一段二进制数据,本身不能够操作内存,需要通过TypedArray 对象或者 DataView 来操作。将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容,其部署了数组接口,可以使用数组的方式来操作数据

TypedArray 视图

最常用的是 TypeArray 视图,用于读写简单类型的 ArrayBuffer,比如 Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图

和 Buffer 的关系

NodeJS 中的 Buffer 类其实是 Uint8Array 的实现。

Buffer 结构

Buffer 是一个类似 Array 的对象,但是它主要用于操作字节

模块结构

Buffer 是 JS 和 C++ 结合的模块,性能部分都由 C++ 实现,非性能部分都是 JS 实现的Untitled 2.png

Buffer 所占用的内存不是由 V8 分配的,属于堆外内存。

对象结构

Buffer 对象类似数组,其元素是16进制的两位数,即0~255的数值

Untitled 3.png

从这个例子能够看出,不同字符在 Buffer 中占据的字节是不一样的,在 UTF-8 编码下,中文占据3个字节,英文和半角标号占用1个字节

? 输入的元素是小数/负数/超出255会发生什么事情?

Untitled 4.png

对于上述这种情况,Buffer 的处理为:

Buffer 里面为什么展示的是16进制

其实在内存存储的依旧是二进制数,只是 Buffer 在显示这内存数据的时候采用了16进制

大小为2字节的 buffer,一共有16 bit ,比如是00000001 00100011,如果直接这样显示不太方便就转成为了16进制<Buffer 01, 23>

Buffer 的创建

Buffer.alloc 和 Buffer.allocUnsafe

创建固定大小的 buffer

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

Untitled 5.png

Buffer.allocUnsafe(size)

分配一个大小为 size 字节的 Buffer,allocUnsafe 执行速度比 alloc 快,我们发现其结果并不像 Buffer.alloc 那样都初始化为 00

Untitled 6.png

当调用 allocUnsafe 时分配的内存段尚未初始化,这样分配内存速度很块,但分配到的内存片段可能包含旧数据。如果在使用的时候不覆盖这些旧数据就可能造成内存泄露,虽然速度快,尽量避免使用

Buffer 模块会预分配一个内部的大小为 Buffer.poolSize 的 Buffer 实例,作为快速分配的内存池,用于使用 allocUnsafe 创建新的 Buffer 实例

Buffer.from

根据内容直接创建Buffer

Untitled 7.png

Buffer.allocUnsafe 的内存机制

为了高效使用申请来的内存,Node.js 采用了 slab 机制进行预先申请、事后分配,是一种动态的管理机制

使用 Buffer.alloc(size) 传入一个指定的 size 就会申请一块固定大小的内存区域,slab 具有如下三种状态

Node.js 使用8 KB 为界限来区分是小对象还是大对象

Untitled 8.png

Buffer 在创建的时候大小就已经被确定了且无法调整!

分配小对象

如果分配的对象小于 8KB,Node 会按着小对象的方式来进行分配

Buffer 的分配过程中主要使用一个局部变量 pool 作为中间处理对象,处于分配状态的 slab 单元都指向它。以下是分配一个全新的 slab 单元的操作,它将会新申请的 SlowBuffer 对象指向它

Untitled 9.png

一个 slab 单元

Untitled 10.png

分配一个 2KB 大小的 Buffer

创建一个 2KB 的 buffer后,一个 slab 单元内存如下:

Untitled 11.png

这个分配过程是由 allocate 方法完成

Untitled 12.png

当我们创建了一个 2KB 的 buffer 之后,当前 slab 状态为 partial

再次创建 buffer 的时候,会去判断当前 slab 剩余空间是否足够。如果足够,使用剩余空间,并更新 slab 的分配状态

如果 slab 空间不够,就会构建新的 slab,原 slab 中剩余的空间造成浪费

分配大对象

如果有超过 8KB 的 buffer,直接会走到 creatUnsafeBuffer 函数,分配一个 slab 单元,这个 slab 单元将会被这个大 Buffer 对象独占

allocate 分配机制如图

Untitled 13.png

Buffer 的内存分配机制

Untitled 14.png

Buffer 和字符编码

通过使用字符编码,可实现 Buffer 实例与 JavaScript 字符串之间的相互转换

Untitled 15.png

Node 中目前支持 utf8、ucs2、utf16le、latin1、ascii、base64、hex、base64Url 八种编码方式,具体实现

Untitled 16.png

针对于每一种不同的编码方案都会用实现一系列 api,返回会有不同的结果,Node.js 会根据传入的 encoding 来返回不同的对象

Buffer 和字符串的转换

字符串转 Buffer

主要通过上述讲的 Buffer.from 方法,默认的 encoding 方式为 utf-8

Buffer 转字符串

Untitled 17.png

? 为什么会出现乱码呢?如何解决这个问题呢?

按着读取来说,我们每次读取的长度为4,chunk输出如下

Untitled 18.png

对于data += chunk等价于data = data.toString + chunk.toString

由于一个中文占据三个字节,第一个 chunk 中的第四个字节会显示乱码,第二个 chunk 的第一第二个字节也无法形成文字等等,所以会展示乱码问题

以上就是深入了解Node中的Buffer的详细内容,更多请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯