Node【三】Buffer 与 Stream

news2025/1/16 4:44:00

文章目录

  • 🌟前言
  • 🌟Buffer
    • 🌟 Buffer结构
    • 🌟 什么时候用Buffer
    • 🌟 Buffer的转换
    • 🌟 Buffer使用
      • 🌟 创建Buffer
      • 🌟 字符串转Buffer
      • 🌟 Buffer转字符串
      • 🌟 拼接Buffer
      • 🌟 Buffer不支持的编码类型
      • 🌟 判断是不是Buffer
      • 🌟 获取字节长度
      • 🌟 判断两个Buffer字节是否相同
  • 🌟Nodejs Stream(流)
    • 🌟 Node.js Stream
    • 🌟为什么应该使用流
    • 🌟Stream的作用
    • 🌟Node.js Stream
    • 🌟四种基本的流类型
      • 🌟1.readStream 读取流
        • 🌟参数
        • 🌟事件
        • 🌟方法
      • 🌟2.writeStream 写入流
        • 🌟 事件
        • 🌟方法
          • 🌟 write()
          • 🌟end()
      • 🌟3.管道流
        • 🌟options
  • 🌟写在最后

在这里插入图片描述

🌟前言

哈喽小伙伴们,新的专栏 Node 已开启;这个专栏里边会收录一些Node的基础知识和项目实战;今天我们开始这个专栏的第三篇文章,带领大家初识一下Buffer 与 Stream;让我们一起来看看吧🤘

🌟Buffer

JavaScript最初是被设计为处理html文档的,因此并不善于处理二进制数据。Node中需要处理网络协议、操作数据库、处理图片、文件上传等,还需要处理大量二进制数据,为此Node提供了Buffer类,该类封装了对访问连续内存块的操作,可以处理内存中的数据及创建、切分缓冲区,还可以在两个缓冲区之间复制内存数据。

🌟 Buffer结构

Buffer是一个典型的Javascript和C++结合的模块,性能相关部分用C++实现,非性能相关部分用javascript实现。

node在进程启动时Buffer就已经加装进入内存,并将其放入全局对象,因此无需require

Buffer对象:类似于数组,其元素是16进制的两位数。

🌟 什么时候用Buffer

纯粹的Javascript支持unicode码而对二进制不是很支持,当解决TCP流或者文件流的时候,处理流是有必要的,我们保存非utf-8字符串,2进制等等其他格式的时候,我们就必须得使用”Buffer“。

🌟 Buffer的转换

Buffer对象可以和字符串相互转换,支持的编码类型如下: ASCII、UTF-8、Base64、Binary(二进制)、Hex(十六进制)

🌟 Buffer使用

方法类型描述
Buffer.from(array)创建array 创建一个新的 Buffer
Buffer.from(string[,encoding])创建新建一个包含所给的 JavaScript 字符串 string 的 Buffer 。 encoding 参数指定 string 的字符编码。
Buffer.alloc(size[,val[,encoding]])创建分配一个大小为 size 字节的新建的 Buffer 。 如果 fill 为 undefined ,则该 Buffer 会用 0 填充。
Buffer.concat(list[,totallength])合并返回一个合并了 list 中所有 Buffer 实例的新建的 Buffer
buf.toString([encoding], [start], [end])返回根据 encoding 指定的字符编码解码 buf 成一个字符串。
buf.toJSON()返回返回 buf 的 JSON 格式。
Buffer.isEncoding(encoding)检测如果 encoding 是一个支持的字符编码则返回 true,否则返回 false 。
Buffer.isBuffer(obj)检测如果 obj 是一个 Buffer 则返回 true ,否则返回 false 。
Buffer.byteLength(buf)获取获取字节长度
buf.equals(otherBuffer)检测如果 buf 与 otherBuffer 具有完全相同的字节,则返回 true,否则返回 false。

🌟 创建Buffer

Buffer.from(array)
Buffer.from(string[,encoding])
Buffer.alloc(size[,val[,encoding]])

🌟 字符串转Buffer

# 默认UTF-8
Buffer.from(string[,encoding])

🌟 Buffer转字符串

buf.toString([encoding], [start], [end])

🌟 拼接Buffer

Buffer.concat(list[,totallength])

🌟 Buffer不支持的编码类型

Buffer.isEncoding(encoding)

🌟 判断是不是Buffer

Buffer.isBuffer(obj)

🌟 获取字节长度

Buffer.byteLength(buf)

🌟 判断两个Buffer字节是否相同

如果 buf 与 otherBuffer 具有完全相同的字节,则返回 true,否则返回 false。

buf.equals(otherBuffer)

🌟Nodejs Stream(流)

在之前我们学习过fs模块,fs模块中有fs.readFile 与 fs.writeFile 这两个方法读取和写入操作,但是这两个方法时将文件作为一个整体做读取、写入操作。

  • fs.readFile 将文件做为整体读入缓存区
  • fs.writeFile 将数据做为整体写入文件

假设我们要读取的文件为100G,内存只有8G,那么内存根本无法容纳这100G的数据,那么我们该如何去操作这些大数据呢?

假设客户端向服务器端传递100G的数据,数据是分为一小段一小段进行传输的。到了服务器端再将其组合起来。

传输数据的时候最小单位就是字节。

🌟 Node.js Stream

Stream是Node.js中处理数据的抽象接口,Node中有很多对象实现了这个接口。

Stream是Node.js中非常重要的一个模块,应用广泛。一个流是一个具备了可读、可写或既可读又可写能力的接口,通过这些接口,我们可以和磁盘文件、套接字、HTTP请求来交互,实现数据从一个地方流动到另一个地方的功能。

例如:对http服务器发起请求的request对象就是一个Stream,还有stdout(标准输出)

🌟为什么应该使用流

在node中,I/O都是异步的,所以在和硬盘以及网络的交互过程中会涉及到传递回调函数的过程。你之前可能会写出这样的代码:

var http = require('http');
var fs = require('fs');

var server = http.createServer(function (req, res) {
    fs.readFile(__dirname + '/data.txt', function (err, data) {
        res.end(data);
    });
});
server.listen(8000);

上面的这段代码并没有什么问题,但是在每次请求时,我们都会把整个data.txt文件读入到内存中,然后再把结果返回给客户端。想想看,如果data.txt文件非常大,在响应大量用户的并发请求时,程序可能会消耗大量的内存,这样很可能会造成用户连接缓慢的问题。

其次,上面的代码可能会造成很不好的用户体验,因为用户在接收到任何的内容之前首先需要等待程序将文件内容完全读入到内存中。

所幸的是,(req,res)参数都是流对象,这意味着我们可以使用一种更好的方法来实现上面的需求:

var http = require('http');
var fs = require('fs');

var server = http.createServer(function (req, res) {
    var stream = fs.createReadStream(__dirname + '/data.txt');
    stream.pipe(res);
});
server.listen(8000);

在这里,.pipe()方法会自动帮助我们监听data和end事件。上面的这段代码不仅简洁,而且data.txt文件中每一小段数据都将源源不断的发送到客户端。

除此之外,使用.pipe()方法还有别的好处,比如说它可以自动控制后端压力,以便在客户端连接缓慢的时候node可以将尽可能少的缓存放到内存中。

🌟Stream的作用

传统程序在执行过程中,会边读边写,读写的速度不一样会导致数据丢失;且内存受限,读取存取速度有限。采用流以后程序会读一部分写一部分,保障数据不缺失。

Stream的作用如下:

  • 保证程序运行效率
  • 防止数据丢失
  • 防止内存的溢出

🌟Node.js Stream

Stream是Node.js中处理数据的抽象接口,Node中有很多对象实现了这个接口。 例如:对http服务器发起请求的request对象就是一个Stream,还有stdout(标准输出)

该stream模块可以使用访问:

const stream = require('stream');

🌟四种基本的流类型

  • Readable - 读取流 (例如 fs.createReadStream())
  • Writable - 写入流 (例如写 fs.createWriteStream())
  • Duplex - 读写流(即双工流) (例如 net.Socket)
  • Transform - 读写流(操作被写入数据,然后读出结果) (例如 zlib.createDeflate())

🌟1.readStream 读取流

fs.createReadStream(path,[opts]);  //创建可读流

🌟参数

  • path 创建读取流指定的文件路径
  • opts
    • flags 对文件采取何种操作,默认为 ‘r’
    • encoding 指定 编码 ,默认为null
    • start 用整数表示文件 开始 读取的字节数的索引位置
    • end 用整数表示文件 结束 读取的字节数的索引位置(包括end位置)
    • highWaterMark 最高水位线,停止从底层资源读取前内部缓冲区最多能存放的字节数。缺省为 64kb
{"encoding":"utf-8","start":0,"end":2,"highWaterMark":4}

🌟事件

  • data 当数据读取的时候
  • end 没有更多的数据可读时触发
  • error 当发生错误时候触发

🌟方法

  • setEncoding 指定 编码
  • pause() 读取数据暂停(什么时候暂停?读入流大于写入流调用)
  • resume() 通知对象 恢复 触发data事件继续读取数据
  • pipe() 管道 由读取流安全的传输到下一个流

🌟2.writeStream 写入流

fs.createWriteStream(path,[opts]);  //创建一个可写入流
  • path 读取的文件路径
  • options
    • flags 对文件采取何种 操作 ,默认为 ‘w’
    • encoding 指定 编码 ,默认为null
    • autoClose 是否 关闭 文件描述符
    • start 用整数表示文件 开始 字节数的写入位置
    • highWaterMark 最高水位线,write()开始返回 false 的 缓冲大小 。缺省为 16kb

🌟 事件

  • drain 当前内存数据完全都写入流的时候触发
  • finish 当数据全部都写完后触发

🌟方法

🌟 write()
write(chunk,[encoding],[callback])

要往写入流写入数据的时候触发

参数

  • chunk 要 写入 的数据,Buffer或字符串对象,必须指定
  • encoding 写入 编码 ,chunk为字符串时有用,可选
  • callback 写入成功后的 回调

返回值为布尔值,系统缓存区定满时为false,未满时为true

🌟end()
writable.end(chunk,[encoding],[callback]);

在写入文件时,当不再需要写入数据时可调用该方法关闭文件。 迫使系 统缓存区的数据立即写入文件中。

🌟3.管道流

管道流,pipe()方法的初衷,是将数据的滞留量限制到一个可接受的水平,以使得不同速度的来源和目标不会淹没可用内存。

readStream.pipe(writeStream,[options]);

🌟options

  • end 为true时表示数据读取完毕后立刻将缓存区中的数据写入目 标文件并 关闭 文件 无论哪一种流,都会使用.pipe()方法来实现输出和输出。
fs.createReadStream().pipe(fs.createWriteStream());
  • pipe()函数很简单,它仅仅是接受一个源头src并将数据输出到一个可写的流dst中:
src.pipe(dst)
  • pipe(dst)将会返回dst因此你可以链式调用多个流:
a.pipe(b).pipe(c).pipe(d)

上面的代码也可以等价为:

a.pipe(b);
b.pipe(c);
c.pipe(d);

🌟写在最后

更多Node知识以及API请大家持续关注,尽请期待。各位小伙伴让我们 let’s be prepared at all times!

✨原创不易,还希望各位大佬支持一下!
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/415722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python 理解BN、LN、IN、GN归一化、分析torch.nn.LayerNorm()和torch.var()工作原理

目录 前言: 简言之BN、LN、IN、GN等归一化的区别: 批量归一化(Batch Normalization,BN) 优点 缺点 计算过程 层归一化(Layer Normalization,LN) 优点 计算过程 总结 分析torch.nn.LayerNorm()工作原理 分析torch.var(…

Vue2-黑马(十一)

目录: (1)vue2-联调准备 (2)vue2-登录实战-国际化 (3)vue2实战-登录-login-index.vue (1)vue2-联调准备 登录这个请求,并不是发给后台的,现在还…

浙大MBA提面申请材料的三六九等……

每年浙大MBA项目提前批面试申请的每个批次中都会有部分材料因为某些原因而被淘汰,无缘面试资格。考生们由最初的不理解到逐渐隐约的理解,行至今日也可以大体接受材料被刷这个结果,当然其中含有一部分面上资质背景还可以的考生,等到…

Faster-RCNN代码解读2:快速上手使用

Faster-RCNN代码解读2:快速上手使用 前言 ​ 因为最近打算尝试一下Faster-RCNN的复现,不要多想,我还没有厉害到可以一个人复现所有代码。所以,是参考别人的代码,进行自己的解读。 ​ 代码来自于B站的UP主(…

中国电子学会2023年03月份青少年软件编程Scratch图形化等级考试试卷四级真题(含答案)

2023-03 Scratch四级真题 分数:100 题数:24 测试时长:90min 一、单选题(共10题,共30分) 1.编写一段程序,从26个英文字母中,随机选出10个加入列表a。空白处应填入的代码是?(C&am…

Flink (十二) --------- Flink CEP

目录一、基本概念1. CEP 是什么2. 模式 (Pattern)3. 应用场景二、快速上手1. 需要引入的依赖2. 一个简单实例三、模式 API(Pattern API)1. 个体模式2. 组合模式3. 模式组4. 匹配后跳过策略四、模式的检测处理1. 将模式应用到流上2. 处理匹配事件3. 处理超…

【高项】项目整体管理、范围管理与进度管理(十大管理)

【高项】项目整体管理与范围管理 文章目录1、项目整体管理1.1 整体管理的过程1.2 制定项目章程(启动)1.3 制订项目管理计划(规划)1.4 指导与管理项目执行(执行)1.5 监控项目工作与实施整体变更控制&#xf…

Systemverilog中operators和expression的记录

1. Equality operators Equality operators有三种: Logical equality:, !,该运算符中如果运算数包含有x/z态,那么结果就是x态。只有在两边的bit都不包含x/z态,最终结果才会为0(False)或1(True)Case equality&#xf…

中云盾DDoS云防护系统

中云盾 DDoS 防护系统作为公司级网络安全产品,为各类业务提供专业可靠的 DDoS/CC 攻击防护。在黑客攻防对抗日益激烈的环境下, DDoS 对抗不仅需要 “降本” 还需要 “增效”。 为什么上云? 云原生作为近年来相当热门的概念,无论…

RHCE-NTP、SSH服务器

1.配置ntp时间服务器,确保客户端主机能和服务主机同步时间​ 服务器端: (1)首先安装chrony软件: dnf install -y chrony (2)配置时间同步源: 进入vim /etc/chrony.conf &#xf…

引用和指针

总结 引用: 因为引用是变量的别名,所以引用必须初始化 因为引用不存在自己的地址,所以指针不能指向引用,即不能定义引用的指针 因为引用不是对象,但是引用又要绑定一个对象,所以不能定义引用的引用 in…

一篇文章看懂C++三大特性——多态的定义和使用

目录 前文 一,什么是多态? 1.1 多态的概念 二, 多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.3.1 虚函数重写的两个例外 2.4 C override 和 final 2.5 重载,重写(覆盖),隐藏(重定义)的区别 三,抽…

代码随想录刷题-双指针总结篇

文章目录双指针移除元素习题我的解法双指针优化反转字符串习题我的解法剑指 Offer 05. 替换空格习题我的解法正确解法反转字符串里的单词习题我的解法反转链表习题我的解法删除链表的倒数第 N 个节点习题我的解法相交链表习题我的解法环形链表 II习题我的解法三数之和习题我的解…

Unity VFX -- (3)创建环境粒子系统

粒子系统中最常用也最重要的一种使用场景是实现天气效果。只需要做很少修改,场景就能很快从蓝天白云变成雪花飘舞。 和之前看到的粒子系统从一个源头发出粒子的情况不同,天气效果完全围绕着场景。 新增和放置一个新的粒子系统 为了创建下雨或下雪的天气…

【从零开始学Skynet】基础篇(三):服务模块常用API

1、服务模块 Skynet提供了开启服务和发送消息的API,必须要先掌握它们。列出了Skynet中8个最重要的API,PingPong程序会用到它们。 Lua API说明newservice(name, ...) 启动一个名为 name 的新服务,并返回服务的地址。 start(func) …

【学习笔记】unity脚本学习(二)(Time时间体系、Random随机数、Mathf数学运算)

目录Time时间体系timeScalemaximumDeltaTimefixedDeltaTimecaptureDeltaTimedeltaTime整体展示Random随机数Mathf数学运算IMathf.Round()Mathf.Ceil() Mathf.CeilToInt()Mathf.SignMathf.ClampMathf数学运算II-曲线变换Lerp 线性插值LerpAngleSmoothDamp疑问:Smooth…

自己动手写编译器:DFA跳转表的压缩算法

在编译器开发体系中有两套框架,一个叫"lex && yacc", 另一个名气更大叫llvm,这两都是开发编译器的框架,我们只要设置好配置文件,那么他们就会生成相应的编译器代码,通常是c或者c代码,然后…

AI自动寻路AStar算法【图示讲解原理】

文章目录AI自动寻路AStar算法背景AStar算法原理AStar寻路步骤AStar具体寻路过程AStar代码实现运行结果AI自动寻路AStar算法 背景 AI自动寻路的算法可以分为以下几种: 1、A*算法:A*算法是一种启发式搜索算法,它利用启发函数(heu…

Jmeter接口测试和性能测试

目前最新版本发展到5.0版本,需要Java7以上版本环境,下载解压目录后,进入\apache-jmeter-5.0\bin\,双击ApacheJMeter.jar文件启动JMemter。 1、创建测试任务 添加线程组,右击测试计划,在快捷菜单单击添加-…

STM32F103RCT6驱动SG90舵机-完成正反转角度控制

一、SG90舵机介绍 SG90是一种微型舵机,也被称为伺服电机。它是一种小型、低成本的直流电机,通常用于模型和机器人控制等应用中。SG90舵机可以通过电子信号来控制其精确的位置和速度。它具有体积小、重量轻、响应快等特点,因此在各种小型机械…