Node 【Buffer 与 Stream】

news2024/10/7 10:21:34

文章目录

  • 🌟前言
  • 🌟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/441914.html

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

相关文章

微信小程序登录注册页面

// login.js // 获取应用实例 var app getApp() var api require("../../utils/api.js")Page({data: {motto: zhenbei V1.0.0,userInfo: {},hasUserInfo: false,disabled: true,btnstate: default,username: ,password: ,canIUse: wx.canIUse(button.open-type.get…

UE4/5 C++网络服务器编程纪录【零】--准备篇

前言 之前利用业余时间重新复习UE4/5的C开发,闲来无事做了个基于独立服务器的多人在线(目前限定客户数量是20人以内)DEMO,核心功能在我之前发的B站视频里面有,战斗、动作、交互以及场景演示都有了,有朋友看…

Linux使用:环境变量指南和CPU和GPU利用情况查看

Linux使用:环境变量指南和CPU和GPU利用情况查看 Linux环境变量初始化与对应文件的生效顺序Linux的变量种类设置环境变量直接运行export命令定义变量修改系统环境变量修改用户环境变量修改环境变量配置文件 环境配置文件的区别profile、 bashrc、.bash_profile、 .ba…

函数(有点难,要注重实战)

目录 1. 函数是什么2. C语言中函数的分类2.1 库函数2.1.1 如何学会使用库函数? 2.2 自定义函数 3. 函数的参数3.1 实际参数(实参):3.2 形式参数(形参): 4. 函数的调用:4.1 传值调用4…

Spark SQL实战(08)-整合Hive

1 整合原理及使用 Apache Spark 是一个快速、可扩展的分布式计算引擎,而 Hive 则是一个数据仓库工具,它提供了数据存储和查询功能。在 Spark 中使用 Hive 可以提高数据处理和查询的效率。 场景 历史原因积累下来的,很多数据原先是采用Hive…

Node内置模块 【url模块与queryString】

文章目录 🌟前言🌟url 模块🌟 URL各部分说明🌟 将URL字符串转换为对象🌟 将对象格式化为URL字符串:url.format(urlObj)🌟 URL路径处理:url.resolve(from, to) 🌟 querySt…

MySQL-四大类日志

目录 🍁MySQL日志分为4大类 🍁错误日志 🍃修改系统配置 🍁二进制日志 🍃查看二进制日志 🍃删除二进制日志 🍃暂时停止二进制日志的功能 🍁事务日志(或称redo日志) 🍁慢查…

SSM整合、环境配置以及详细综合测试(单表查询、多表查询和数据分页、前后端分离、Vue3)

SSM整合、环境配置以及基础综合测试 准备:创建maven项目以及项目框架准备 SSM整合简介 介绍: SSM(SpringSpringMVCMyBatis) 整合,就是三个框架协同开发。Spring整合Mybatis就是将Mybatis核心配置文件当中数据源的配置、事务处理、以及工厂的配置&…

OpenGL入门教程之 深入三角形

一、引言 本教程使用GLEW和GLFW库。  通过本教程,你能轻松的、深入的理解OpenGL如何绘制一个三角形。  如果你不了解OpenGL是什么,可以阅读OpenGL深入理解。 二、基本函数和语句介绍 通过阅读以下的函数,你的大脑里能留下关于OpenGL基本函…

通过CSIG—走进合合信息探讨生成式AI及文档图像处理的前景和价值

一、前言 最近有幸参加了由中国图象图形学学会(CSIG)主办,合合信息、CSIG文档图像分析与识别专业委员会联合承办的“CSIG企业行——走进合合信息”的分享会,这次活动以“图文智能处理与多场景应用技术展望”为主题,聚…

安全防御第四天:防病毒网关

一、恶意软件 1.按照传播方式分类 (1)病毒 病毒是一种基于硬件和操作系统的程序,具有感染和破坏能力,这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地,它是病毒传播的目的地,又是下一次感染的出…

尚融宝21-整合springcloud

目录 一、整合注册中心nacos 二、整合openFeign (一)准备工作 (二)导入依赖 (三)接口的远程调用 (四)配置超时控制和日志打印 三、整合Sentinel 四、整合gateway服务网关 …

【Spring从成神到升仙系列 五】从根上剖析 Spring 循环依赖

👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…

基于SpringBoot+Vue家乡特色推荐系统

您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦。 💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精…

【李老师云计算】HBase+Zookeeper部署及Maven访问(HBase集群实验)

索引 前言1. Zookeeper1.1 主机下载Zookeeper安装包1.2 主机解压Zookeeper1.3 ★解决解压后文件缺失1.4 主机配置Zookeeper文件1.4.1 配置zoo_sample.cfg文件1.4.2 配置/data/myid文件 1.5 主机传输Zookeeper文件到从机1.6 从机修改Zookeeper文件1.6.1 修改zoo.cfg文件1.6.2 修…

一文带你了解MySQL的前世今生,架构,组成部分,特点,适用场景

文章目录 一、MySQL的由来二、MySQL的架构2.1 客户端2.2 服务器 三、 MySQL的主要组成部分3.1 连接管理器3.2 查询缓存3.3 解析器3.4 查询优化器3.5 执行器3.6 存储引擎 四、MySQL的特点五、MySQL的应用场景六、总结 一、MySQL的由来 MySQL最初是由瑞典公司MySQL AB的Michael …

4年功能测试,我一进阶python接口自动化测试,跳槽拿了20k......

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 很多人在这求职市…

让ChatGPT告诉你Java的发展前景

Java版电商购物系统项目实战 最近很多人问我Java的发展前景怎么样?该怎么学Java基础?java这么卷还该不该学等等。那今天老王以电商场景为例,再结合ChatGPT的回答和大家聊的一下Java有哪些应用前景和技术层面的落地方案。(在收获干…

【Spring】-- 02 -- Spring中Bean的配置、作用域

一、Bean的配置 Spring用于生产和管理Spring容器中的Bean,需要开发者对Spring的配置文件进行配置。在实际开发中,最常采用XML格式的配置方式,即通过XML文件来注册并管理Bean之间的依赖关系。 在Spring中,XML配置文件的根元素是…

iOS问题记录 - Xcode 14.3版本运行项目报错

文章目录 前言开发环境问题描述问题分析解决方案最后 前言 看到Xcode有新版本,没忍住点了升级,然后问题来了。 开发环境 macOS 13.3Xcode: 14.3 问题描述 Xcode 14.2版本运行项目一切正常,升级到14.3版本后运行报错。 运行到模拟器的报…