【Node】Buffer 与 Stream

2024-09-07 22:38
文章标签 stream node buffer

本文主要是介绍【Node】Buffer 与 Stream,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

node 为什么会出现 Buffer 这个模块

在最初的时候,JavaScript 只运行在浏览器端,

对于处理 Unicode 编码的字符串很容易,但是对于处理二进制以及非 Unicode 编码的数据便无能为力。

不过对于 Server 端操作来说 网络I/O 以及 文件I/O 的处理是必须的,所以 Node 中便提供了 Buffer 类处理二进制的数据。

二进制缓冲区 Buffer

一个 Buffer 类似于一个整数数组,可以取下标,有length属性,有剪切复制操作等,很多API也类似数组,但Buffer的大小在被创建时确定,且无法调整。

Buffer 可以与 String 互相转化,还可以设置字符集编码。

Buffer 用来处理文件 I/O、网络 I/O传输的二进制数据,String 用来呈现。

在处理文件 I/O、网络 I/O传输的二进制数据时,应该尽量以 Buffer 形式直接传输,速度会得到很好的提升。

Buffer 是一个典型的 JavaScript 与 C++ 结合的模块,与性能有关的用 C++ 来实现,JavaScript 负责衔接和提供接口。

Buffer 所占的内存不是 V8 堆内存,是独立于 V8 堆内存之外的内存,通过 C++ 层面实现内存申请。

可以说真正的内存是 C++层面提供的,而JavaScript分配内存 可以说是 JavaScript层面只是使用它。

小结:Buffer 所占用的内存不是通过 V8 分配的,属于 堆外内存

为了高效使用申请来的内存,Node 采用了 slab分配机制。slab 具有如下3种形态:

  • full:完全分配状态
  • partial:部分分配状态
  • empty:未被分配状态

Node 以 8KB 为界限来区分 Buffer 是大对象还是小对象:

Buffer.poolSize = 8 * 1024;

Buffer 对象是在 JavaScript层面的,能被 V8 的垃圾回收标记回收。

但是其内部的 parent 指向的 SlowBuffer 对象却来自于 Node 自身的 C++ 中的定义,是 C++层面上的Buffer 对象,所用内存不在 V8 的堆中。

小结:

真正的内存是在 Node 的 C++ 层面提供的,JavaScript 层面只是使用它。

当进行小而频繁的 Buffer 操作时,采用 slab 的机制进行预先申请和事后分配,使得 JavaScript 到操作系统之间不必有过多的内存申请方面的系统调用。

对于大块的 Buffer 而言,则直接使用 C++ 层面提供的内存,无需细腻的分配操作。

由于 Buffer太过常见,Node 进程在启动时就已经加载了它,并将其放在全局对象(global)上。所以在使用 Buffer时,无需通过 require() 即可直接使用。

Buffer 字符编码

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

  • ascii —— 仅适用于7位ASCII数据。此编码速度很快,如果设置则会剥离高位。
  • utf8 —— 多字节编码的 Unicode字符。许多网页和其他文档格式都是用UTF-8。
  • base64 —— Base64编码。当从字符串创建Buffer时,此编码也会正确地接受RFC 4648第5节中指定的“URL和文件名安全字母”。
  • binary —— 一种将 Buffer编码成单字节编码字符串的方法。
  • hex —— 将每个字节编码成两个十六进制的字符。
字符串 与 Buffer类型互传

字符串转 Buffer:Buffer.from()

const buf = Buffer.from('Node.js 技术栈', 'UTF-8');console.log(buf); // <Buffer 4e 6f 64 65 2e 6a 73 20 e6 8a 80 e6 9c af e6 a0 88>
console.log(buf.length); // 17

Buffer 转字符串:toString([encoding], [start], [end])

const buf = Buffer.from('Node.js 技术栈', 'UTF-8');console.log(buf); // <Buffer 4e 6f 64 65 2e 6a 73 20 e6 8a 80 e6 9c af e6 a0 88>
console.log(buf.length); // 17
console.log(buf.toString('UTF-8', 0, 9)); // 'Node.js �'

运行查看,可以看到以上输出结果为 Node.js �, 出现了乱码。

转换过程中为什么出现乱码?

问题出在这里一个中文在UTF-8下占用3个字节,“技”这个字在 buf 中对应的字节为 8a80e6,而我们设定的范围为0~9,

因此只输出了8a,这个时候就会造成字符被截断,出现乱码的情况。要想完整出现“技”这个字,则应该截取到11位。

console.log(buf.toString('UTF-8', 0, 11)); // 'Node.js 技'
Buffer 的拼接

Buffer 在使用场景中,通常是以一段一段的方式传输。

var fs = require('fs');var rs = fs.createReadStream('test.txt');
var dat

这篇关于【Node】Buffer 与 Stream的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146363

相关文章

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

nvm如何切换与管理node版本

《nvm如何切换与管理node版本》:本文主要介绍nvm如何切换与管理node版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录nvm切换与管理node版本nvm安装nvm常用命令总结nvm切换与管理node版本nvm适用于多项目同时开发,然后项目适配no

Java之并行流(Parallel Stream)使用详解

《Java之并行流(ParallelStream)使用详解》Java并行流(ParallelStream)通过多线程并行处理集合数据,利用Fork/Join框架加速计算,适用于大规模数据集和计算密集... 目录Java并行流(Parallel Stream)1. 核心概念与原理2. 创建并行流的方式3. 适

Go 1.23中Timer无buffer的实现方式详解

《Go1.23中Timer无buffer的实现方式详解》在Go1.23中,Timer的实现通常是通过time包提供的time.Timer类型来实现的,本文主要介绍了Go1.23中Timer无buff... 目录Timer 的基本实现无缓冲区的实现自定义无缓冲 Timer 实现更复杂的 Timer 实现总结在

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

Java 8 Stream filter流式过滤器详解

《Java8Streamfilter流式过滤器详解》本文介绍了Java8的StreamAPI中的filter方法,展示了如何使用lambda表达式根据条件过滤流式数据,通过实际代码示例,展示了f... 目录引言 一.Java 8 Stream 的过滤器(filter)二.Java 8 的 filter、fi

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ