0

0

深入了解Node中的Buffer

青灯夜游

青灯夜游

发布时间:2023-04-25 19:49:11

|

2737人浏览过

|

来源于掘金社区

转载

深入了解Node中的Buffer

在 Stream 篇结中,我们留下了一个问题,下述代码输出的 chunk 是一个什么东西?

Untitled.png

通过打印,我们发现 chunk 是 Buffer 对象,其中的元素是16进制的两位数,即0~255的数值。【相关教程推荐:nodejs视频教程编程教学

Untitled 1.png

说明在 Stream 中流动的数据就是 Buffer,那下面就让我们来探究一下 Buffer 的真实面目!

? Node 中为什么要引入 Buffer?

最开始的时候 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 的处理为:

  • 给元素的赋值小于0, 就将该值逐次加256,直到得到一个0到255之间的整数
  • 如果得到的数值大于255,就逐次减256,直到得到0~255区间内的数值
  • 如果是小数,只保留整数部分

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

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

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

Buffer 的创建

Buffer.alloc 和 Buffer.allocUnsafe

创建固定大小的 buffer

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

  • size 新 Buffer 的所需长度
  • fill 用于预填充新 Buffer 的值。默认值: 0
  • encoding 如果 fill 是一个字符串,则这是它的字符编码。默认值: utf8

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

  • Buffer.from(string [, encoding])
  • Buffer.from(array)
  • Buffer.from(buffer)

Untitled 7.png

Buffer.allocUnsafe 的内存机制

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

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

mallcloud商城
mallcloud商城

mallcloud商城基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离vue的企业级微服务敏捷开发系统架构。并引入组件化的思想实现高内聚低耦合,项目代码简洁注释丰富上手容易,适合学习和企业中使用。真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案,面向互联网设计同时适合B端和C端用户,支持CI/CD多环境部署,并提

下载
  • full: 完全分配状态
  • partial:部分分配状态
  • empty:没有被分配状态

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相关知识,请访问:nodejs 教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

6

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

8

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

14

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

17

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

2

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

130

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

8

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

208

2026.02.27

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 12.3万人学习

CSS3 教程
CSS3 教程

共18课时 | 6.3万人学习

Vue 教程
Vue 教程

共42课时 | 9万人学习

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

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