目录
ArrayBuffer
是什么
TypedArray 视图
和 Buffer 的关系
Buffer 结构
模块结构
对象结构
Buffer 的创建
Buffer.alloc 和 Buffer.allocUnsafe
Buffer.alloc(size [, fill [, encoding]])
Buffer.allocUnsafe(size)
Buffer.from
Buffer.allocUnsafe 的内存机制
分配小对象
分配一个 2KB 大小的 Buffer
分配大对象
Buffer 的内存分配机制
Buffer 和字符编码
Buffer 和字符串的转换
字符串转 Buffer
Buffer 转字符串
首页 web前端 js教程 深入了解Node中的Buffer

深入了解Node中的Buffer

Apr 25, 2023 pm 07:49 PM
前端 node.js

深入了解Node中的Buffer

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

深入了解Node中的Buffer

通过打印,我们发现 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 具有如下三种状态

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

以上是深入了解Node中的Buffer的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP与Vue:完美搭档的前端开发利器 PHP与Vue:完美搭档的前端开发利器 Mar 16, 2024 pm 12:09 PM

PHP与Vue:完美搭档的前端开发利器在当今互联网高速发展的时代,前端开发变得愈发重要。随着用户对网站和应用的体验要求越来越高,前端开发人员需要使用更加高效和灵活的工具来创建响应式和交互式的界面。PHP和Vue.js作为前端开发领域的两个重要技术,搭配起来可以称得上是完美的利器。本文将探讨PHP和Vue的结合,以及详细的代码示例,帮助读者更好地理解和应用这两

如何使用 Go 语言进行前端开发? 如何使用 Go 语言进行前端开发? Jun 10, 2023 pm 05:00 PM

随着互联网技术的发展,前端开发变得日益重要。尤其是移动端设备的普及,更需要高效、稳定、安全又易维护的前端开发技术。而作为一门快速发展的编程语言,Go语言已经被越来越多的开发者所使用。那么,使用Go语言进行前端开发行得通吗?接下来,本文将为你详细说明如何使用Go语言进行前端开发。先来看看为什么使用Go语言进行前端开发。很多人认为Go语言是一门

前端面试官常问的问题 前端面试官常问的问题 Mar 19, 2024 pm 02:24 PM

在前端开发面试中,常见问题涵盖广泛,包括HTML/CSS基础、JavaScript基础、框架和库、项目经验、算法和数据结构、性能优化、跨域请求、前端工程化、设计模式以及新技术和趋势。面试官的问题旨在评估候选人的技术技能、项目经验以及对行业趋势的理解。因此,应试者应充分准备这些方面,以展现自己的能力和专业知识。

Django是前端还是后端?一探究竟! Django是前端还是后端?一探究竟! Jan 19, 2024 am 08:37 AM

Django是一个Python编写的web应用框架,它强调快速开发和干净方法。尽管Django是一个web框架,但是要回答Django是前端还是后端这个问题,需要深入理解前后端的概念。前端是指用户直接和交互的界面,后端是指服务器端的程序,他们通过HTTP协议进行数据的交互。在前端和后端分离的情况下,前后端程序可以独立开发,分别实现业务逻辑和交互效果,数据的交

golang可以做前端吗 golang可以做前端吗 Jun 06, 2023 am 09:19 AM

golang可以做前端,Golang是一种通用性很强的编程语言,可以用于开发不同类型的应用程序,包括前端应用程序,通过使用Golang来编写前端,可以摆脱JavaScript等语言引起的一系列问题,例如类型安全性差、性能低下,以及代码难以维护等问题。

C#开发经验分享:前端与后端协同开发技巧 C#开发经验分享:前端与后端协同开发技巧 Nov 23, 2023 am 10:13 AM

作为一名C#开发者,我们的开发工作通常包括前端和后端的开发,而随着技术的发展和项目的复杂性提高,前端与后端协同开发也变得越来越重要和复杂。本文将分享一些前端与后端协同开发的技巧,以帮助C#开发者更高效地完成开发工作。确定好接口规范前后端的协同开发离不开API接口的交互。要保证前后端协同开发顺利进行,最重要的是定义好接口规范。接口规范涉及到接口的命

Go语言前端技术探秘:前端开发新视野 Go语言前端技术探秘:前端开发新视野 Mar 28, 2024 pm 01:06 PM

Go语言作为一种快速、高效的编程语言,在后端开发领域广受欢迎。然而,很少有人将Go语言与前端开发联系起来。事实上,使用Go语言进行前端开发不仅可以提高效率,还能为开发者带来全新的视野。本文将探讨使用Go语言进行前端开发的可能性,并提供具体的代码示例,帮助读者更好地了解这一领域。在传统的前端开发中,通常会使用JavaScript、HTML和CSS来构建用户界面

Golang与前端技术结合:探讨Golang如何在前端领域发挥作用 Golang与前端技术结合:探讨Golang如何在前端领域发挥作用 Mar 19, 2024 pm 06:15 PM

Golang与前端技术结合:探讨Golang如何在前端领域发挥作用,需要具体代码示例随着互联网和移动应用的快速发展,前端技术也愈发重要。而在这个领域中,Golang作为一门强大的后端编程语言,也可以发挥重要作用。本文将探讨Golang如何与前端技术结合,以及通过具体的代码示例来展示其在前端领域的潜力。Golang在前端领域的作用作为一门高效、简洁且易于学习的

See all articles