iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > 其他 >深入了解Node中的Buffer
  • 917
分享到

深入了解Node中的Buffer

前端Node.js 2023-05-14 23:05:59 917人浏览 安东尼
摘要

最开始的时候 js 只在浏览器端运行,对于 Unicode 编码的字符串容易处理,但是对于二进制和非 Unicode 编码的字符串处理困难。并且二进制是计算机最底层的数据格式,视频/音频/程序/网络包都是以二进制来存储的。所以 node 需

最开始的时候 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 01, 23>

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中的Buffer的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: 深入了解Node中的Buffer

本文链接: https://www.lsjlt.com/news/207929.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 深入了解Node中的Buffer
    最开始的时候 JS 只在浏览器端运行,对于 Unicode 编码的字符串容易处理,但是对于二进制和非 Unicode 编码的字符串处理困难。并且二进制是计算机最底层的数据格式,视频/音频/程序/网络包都是以二进制来存储的。所以 Node 需...
    99+
    2023-05-14
    前端 Node.js
  • 一文带你深入了解Node中的Buffer类
    简单来说所谓的Buffer就是Node在V8堆内存之外分配的一块固定大小的内存空间。当Buffer被用console.log打印出来时,会以字节为单位,打印出一串以十六进制表示的值。创建Buffer了解完Buffer的基本概念后,我们再来创...
    99+
    2023-05-14
    前端 Node.js JavaScript
  • 深入了解Node的多进程服务实现
    目录1. child_process 模块2. spawn3. fork4. exec 和 execFile5. 各方法之间的比较5.1 spawn 和 execFile5.2 ex...
    99+
    2024-04-02
  • 深入了解Node事件循环(EventLoop)机制
    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。下面本篇文章就来带大家掌握Node.js中的eventloop,希望对大家有所帮助!虽然js可以在浏览器...
    99+
    2023-05-14
    javascript Node.js 面试 前端
  • 深入浅析Node中的Stream(流)
    和上面的示例对比起来,我们发现一个流同时面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform背压问题什么是背压背压问题来源于生产者消费者模式中,消费者处理速度过慢比如说,我...
    99+
    2023-05-14
    前端 Node.js
  • node中的buffer有什么用
    本文小编为大家详细介绍“node中的buffer有什么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“node中的buffer有什么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2024-04-02
  • 深入了解Python中的变量
    目录1 Python变量概述2 Python变量的命名3 Python变量赋值3.1 Python赋值概述3.2 Python变量的基本格式3.3 Python变量的其他赋值格式3....
    99+
    2024-04-02
  • 深入浅析Node中的util.promisify()函数
    Node.js 内置的 util 包有一个 promisify() 函数,可以将基于回调的函数转换为基于 Promise 的函数。本文就来给大家介绍一下Node.js 中的 util.promisify() 函数,希望对大家有所帮助。让你可...
    99+
    2023-05-14
    JavaScript Node.js
  • Node中的Buffer类怎么使用
    这篇文章主要介绍了Node中的Buffer类怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Node中的Buffer类怎么使用文章都会有所收获,下面我们一起来看看吧。在TypedArray出来之前,Jav...
    99+
    2023-07-04
  • 深入聊聊Node中的File模块
    在聊 Stream/Buffer 的时候,我们已经开始使用require("fs")引入文件模块做一些操作了文件模块是对底层文件操作的封装,例如文件读写/打开关闭/删除添加等等文件模块最大的特点就是所有的方法都提供的同步...
    99+
    2023-05-14
    Node.js 前端
  • 深入了解zhparser
    瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台:N/A 版本:14 文档用途 本文参考《zhparser全文检索》,文章ID:051686104;对其进行互补,对zhparser进行进一步...
    99+
    2023-10-27
    postgresql 数据库 php
  • 深入了解JavaScriptPromise
    目录一 什么是 Promise?二 为什么有 Promise?三 Promise常用api四 Promise常用的两个用法总结一 什么是 Promise? 一个 Promise 对...
    99+
    2024-04-02
  • 如何深入了解Redis中的Codis
    这篇文章给大家介绍如何深入了解Redis中的Codis,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。场景在大数据高并发场景下,使用单个redis实例,即使redis的性能再高,也会变的...
    99+
    2024-04-02
  • 深入了解Golang中的run方法
    Go是一种快速,可靠和开源的编程语言。Go语言通过其高效的并发性和垃圾回收器以及C的速度,用于构建高效和可扩展的网络服务器和系统编程。让我们深入了解Golang中的run方法。run()方法是golang中重要的一种方法,可以用于创建新的协...
    99+
    2023-05-14
  • python中jieba模块的深入了解
    目录一、前言        二、模块的安装三、jieba模块具体讲解3.1分词模式3.2cut()、lcut()3.2.1cut(s...
    99+
    2024-04-02
  • 深入了解HTML中的video元素
    HTML中video视频标签详解 HTML5中的video标签是一种用于在网页上播放视频的标签。它可以使用不同的格式来呈现视频,例如MP4、WebM、Ogg等等。在本篇文章中,我们将详...
    99+
    2024-02-24
    html 标签 video
  • 深入了解Python中的os.path.join函数
    深入了解Python中的os.path.join函数 1. 引言 在Python中,处理文件和目录路径是常见的任务。为了简化路径的拼接和操作,Python提供了os.path模块,其中的join函数是...
    99+
    2023-09-08
    python 开发语言
  • 深入了解PHP中的Request概念
    标题:深入了解PHP中的Request概念 在PHP编程中,Request是一个非常重要的概念,它代表着客户端向服务器发送的请求。了解Request的机制可以帮助我们更好地处理用户输入...
    99+
    2024-02-27
    php request 概念 表单提交
  • 深入了解golang中的的泛型(Generic)
    本篇文章给大家带来的内容是介绍深入理解golang中的泛型?泛型怎么使用?有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助。什么是泛型泛型(Generic)是一种编程技术。在强类型语言中, 允许编写代码时使用以后才指定的类型, ...
    99+
    2023-05-14
    Go 后端
  • 深入了解Spring中的@Autowired和@Resource注解
    目录@Autowired@Resource总结应用场景@Resource和@Autowired是Spring Framework中两种常用的注入方式,它们的作用是在Spring容器中...
    99+
    2023-05-17
    Spring @Autowired和@Resource Spring @Autowired Spring @Resource
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作