深入了解Node中的Buffer

深入了解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.alloc 和 Buffer.allocUnsafe

创建固定大小的 buffer

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

size 新 Buffer 的所需长度fill 用于预填充新 Buffer 的值。默认值: 0encoding 如果 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 具有如下三种状态

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

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

知了zKnown 知了zKnown

知了zKnown:致力于信息降噪 / 阅读提效的个人知识助手。

知了zKnown 65 查看详情 知了zKnown

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 教程!

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/541275.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Composer如何强制使用某个依赖版本
上一篇 2025年11月9日 15:26:35
华硕bios怎么调左右
下一篇 2025年11月9日 15:26:41

相关推荐

  • 动态表单输入中多答案数据处理教程

    本教程旨在解决Web开发中,如何高效处理包含动态数量答案的表单提交数据,特别是当需要更新现有问题及其关联答案时。文章将详细阐述前端表单的命名策略以及后端PHP如何解析这些动态输入,以准确获取答案内容及其对应的数据库ID,从而实现数据的精准更新,并提供最佳实践建议。 理解动态答案更新的挑战 在构建问答…

    2026年9月24日
    000
  • PHP Web开发:高效处理动态数量问题答案的表单更新与ID获取

    本教程探讨在PHP Web开发中,如何高效处理具有动态数量答案的问题更新表单。针对需要同时获取答案文本值及其对应ID的场景,文章详细介绍了通过合理设计表单字段命名和利用$_POST超全局变量的键值迭代特性,实现对动态生成答案字段的准确解析和数据提取,确保更新操作的完整性。 问题背景与挑战 在开发问答…

    2026年9月24日
    100
  • Laravel Blade中条件隐藏元素的优雅实践

    本文探讨了在Laravel Blade模板中如何高效地实现HTML元素的条件隐藏。针对传统@if-@else语句导致代码冗余的问题,教程提出使用Blade的内联三元运算符在style属性中动态控制display: none,从而避免重复代码,提升模板的可读性和维护性。此外,还将介绍如何利用CSS类和…

    2026年9月24日
    100
  • VSCode主题开发:创建动态色彩主题的进阶技术解析

    动态主题需通过外部插件监听系统事件实现,核心是利用vscode.themeColor API响应主题切换,结合语义化作用域与Semantic Highlighting精准控制配色逻辑,实现智能自适应视觉体验。 想让VSCode主题随环境自动切换色彩?动态主题不只是换个配色那么简单。核心在于理解VSC…

    2026年9月23日
    400
  • VS Code自动化测试:持续集成与测试覆盖率

    VS Code通过插件和工具集成支持自动化测试、CI流程与覆盖率分析。①配置Jest或pytest等框架,结合Test Explorer UI插件实现测试运行与调试;②利用GitHub Actions等CI服务,在代码推送后自动执行测试,通过插件在编辑器内查看状态;③启用Coverage Gutte…

    2026年9月23日
    100
  • win11耳机插上没反应怎么办_win11耳机无声音故障排查与修复

    首先检查耳机物理连接并测试设备是否正常,确认Windows默认播放设备设置正确,更新或重装音频驱动程序,确保Windows Audio及相关服务已启动,运行系统音频疑难解答工具,并检查Realtek音频管理器中的插孔检测设置。 如果您在Windows 11系统中插入耳机后没有声音或设备无反应,可能是…

    2026年9月23日
    900
  • 如何在mysql中使用连接池提升并发

    连接池通过复用数据库连接减少开销,提升高并发下系统性能;需根据语言选择HikariCP、SQLAlchemy等组件,合理配置最大连接数、空闲连接等参数,并结合数据库优化与监控调优以充分发挥效果。 在高并发场景下,频繁创建和销毁数据库连接会带来显著的性能开销。MySQL本身不直接提供连接池功能,但可以…

    2026年9月23日
    300
  • Descript的AI混合工具怎么用?简化音频与视频编辑的完整教程

    Descript通过文本编辑模式革新音视频剪辑,将转录、填充词去除、音质优化等AI功能融入文档式操作,显著提升内容创作效率与质量。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ Descript的AI混合工具通过将音视频编辑转化为直观的文本…

    2026年9月23日
    200
  • 在PHP中将JSON数组值声明为变量

    本文介绍了如何在PHP中从数据库获取数据并将其编码为JSON数组,然后通过AJAX调用将其传递到另一个页面。重点讲解了如何在接收数据的页面中解析JSON数据,并将JSON数组中的特定值提取为PHP变量,以便在后续的函数或查询中使用。 从数据库获取数据并编码为JSON 首先,我们需要从数据库中获取数据…

    2026年9月23日
    1200
  • 前端危!Gemini 3 内测结果获网友一致好评,“有史以来最强前端开发模型”

    前端危!Gemini 3 内测结果获网友一致好评,“有史以来最强前端开发模型”前端危!Gemini 3 内测结果获网友一致好评,“有史以来最强前端开发模型”前端危!Gemini 3 内测结果获网友一致好评,“有史以来最强前端开发模型”前端危!Gemini 3 内测结果获网友一致好评,“有史以来最强前端开发模型”

    谷歌下一代旗舰模型gemini 3未发布便已悄然走红! 原因很简单:强,实在是太强了。 在国外社交媒体平台上,一大波网友激动地分享了 Gemini 3 的内测结果—— 从曝光的这些案例来看,Gemini 3尤为擅长前端、SVG 矢量图生成,而且多模态能力变得更强。 立即学习“前端免费学习笔记(深入)…

    2026年9月23日 用户投稿
    100
  • Spring Security控制器测试中403错误排查与解决方案

    本文探讨Spring Security控制器测试中遇到403错误的常见原因及解决方案。当安全配置要求特定角色(如ADMIN)访问所有端点时,测试环境下的模拟用户权限可能不匹配。教程将指导如何通过临时放宽安全规则或确保模拟用户角色正确配置来解决此类权限问题,确保测试顺利进行。 在spring secu…

    2026年9月23日
    200
  • 使用 Dompdf 高效生成大量 PDF:优化长时任务与超时处理

    本文探讨了在使用 Dompdf 生成大量或多页 PDF 文件时遇到的超时问题。针对Web环境下的限制,文章提出了两种解决方案:短期内可通过调整PHP执行时间限制来缓解,但更推荐采用PHP命令行接口(CLI)进行后台处理。通过将耗时任务转移到独立的CLI脚本中执行,可以有效避免Web服务器超时,提升P…

    2026年9月23日
    100
  • PHP多维数组重构:按指定键值分组数据

    本文将详细介绍如何在PHP中将扁平化的关联数组列表重构为多维数组,核心思路是根据数组中某个特定键(例如 object_type)的值进行分组,将具有相同键值的所有子数组归集到同一个父级键下,从而实现数据的层次化组织,提高数据的可读性和管理效率。 引言:数据重构的需求 在PHP开发中,我们经常会遇到需…

    2026年9月23日
    100
  • Prestashop分类描述在分页时的显示行为解析与SEO考量

    Prestashop商店中,分类描述通常仅在首个分页页面显示,而在后续分页页面上消失,甚至从第二页返回第一页时也可能不显示。这并非一个技术故障,而是Prestashop的默认行为,且从SEO角度看,只要描述在直接访问的第一页可见,就已满足核心要求,无需在所有分页页面重复显示,以避免潜在的重复内容问题…

    2026年9月23日
    100
  • Prestashop分类页描述与分页:SEO考量及前端行为解析

    本文深入探讨Prestashop电商平台中分类页面描述在分页操作时消失的常见现象。我们将解析其背后的技术原理,重点从搜索引擎优化(SEO)角度阐述为何此行为并非核心问题,并强调确保分类描述在首页面加载时的完整性至关重要。同时,文章也提供若需自定义此行为的思路。 Prestashop分类页描述的分页行…

    2026年9月23日
    200
  • 嵌入式Linux开发-根文件系统本地挂载

    嵌入式Linux开发-根文件系统本地挂载嵌入式Linux开发-根文件系统本地挂载嵌入式Linux开发-根文件系统本地挂载嵌入式Linux开发-根文件系统本地挂载

    引言 前一篇文章介绍了根文件系统的制作与nfs网络挂载,本文将探讨如何通过本地挂载根文件系统来完成系统启动。本地挂载通常用于产品发布阶段,并且分为两种操作方式。 第一种方式:在PC机上制作好文件映像rootfs.img,然后通过uboot加载并直接烧写到EMMC中。这种方法最便捷,适用于产品批量生产…

    2026年9月23日 用户投稿
    300
  • Laravel Eloquent:优化消息查询以获取最新记录

    本文探讨了在 laravel 中如何高效地查询用户消息,以获取与特定用户相关的所有最新消息记录。通过摒弃传统的 sql `join` 和 `group by` 组合在复杂场景下的局限性,我们推荐使用 eloquent 关系和预加载机制。这种方法不仅能避免 `group by` 可能导致的非预期结果,…

    2026年9月23日
    200
  • 使用PHP和Ajax实现搜索结果的A-Z排序

    在PHP搜索结果页面实现A-Z排序功能,可以极大地提升用户体验。结合Ajax技术和PHP后端排序逻辑,我们可以在不刷新页面的情况下实现排序功能。以下将详细介绍实现步骤。 1. 前端:创建排序表单和Ajax请求 首先,需要在 search.php 页面中创建一个表单,用于触发排序操作。这个表单可以包含…

    2026年9月23日
    100
  • 配置php递归函数处理递归转换_通过php递归函数转换数据格式

    递归函数通过自我调用处理树形结构,需有终止条件和问题缩小机制;示例中将扁平数组按parent_id构建为嵌套树,反之亦可展平为带层级的列表,适用于菜单、分类等无限级数据操作。 在PHP开发中,经常需要处理树形结构数据,比如分类、菜单、评论嵌套等。这类数据通常具有父子关系,且层级不确定,这时就需要使用…

    2026年9月23日
    300
  • 如何使用Java制作简易的博客系统

    首先搭建Spring Boot后端,设计BlogPost实体类并用JPA实现数据持久化,通过BlogController处理页面请求,使用Thymeleaf模板引擎渲染index和create页面,配置H2内存数据库并启用控制台,最终实现文章的发布与展示功能。 用Java制作一个简易的博客系统,核心…

    2026年9月23日
    200

发表回复

登录后才能评论
关注微信