一次搞定Node-Stream

前言


🤡在前端我们一般很少接触到流的概念,如果你接触过RxJS的话,你可能会对这个概念比较熟悉,但是在服务器开发流是一个非常重要的概念,但是相对于其他的概念来讲比较难理解,那么就让我们一次性来搞定这个疑难杂症吧~

一.认识Stream


😀什么是Stream(小溪,小河,在编程中通常翻译为流),提到流我们的第一反应应该是流水,流动的小溪,源源不断的流动,其实程序之中的流这样的概念,我们可以想象当我们从一个文件中读取数据时,文件的二进制(字节)数据会源源不断的被读取到我们的程序中,是连续字节的一种表现形式和抽象概念,流应该是可读的也是可写的。

🐻当然学到这里其实就有疑问了,为什么文件的读取我们前面都是通过readFilewriteFile方式来读取和操作文件,为什么还需要流哪?

  1. 直接读取的文件的方式虽然简单,但是无法控制一些细节。
  2. 比如从什么位置读,读到什么位置,一次性读取多少个字节。
  3. 读到某个位置的时候,暂停读取,在某个时刻恢复读取等等。
  4. 或者文件非常的大,比如一个视频文件,一次性全部读取是非常不合适的。

🦝实际上在Node中很多对象都是基于流来实现的

  1. http模块的RequestResponse对象

😈Node.js中有四种基本流类型

  1. Writable:可以向其写入数据的流(例如:fs.createWriteStream())
  2. Readable:可以从中读取数据的流(例如:fs.createReadStream())
  3. Duplex:同时为Readable和Writeable,又被称为双工流(例如:net.Socket)
  4. Transform:Duplex可以在写入和读取数据时修改或者转换数据的流(例如:zlib.createDeflate())

二.可读流的基本使用


🥺我们知道我们之前读取文件一般使用fs模块中的数据进行去读,这样读取的方式会有很多的问题,主要缺点如下

  1. 没有办法精准的控制从什么地方读取,读取到某个位置。
  2. 读取到某一个位置的,暂停读取,恢复读取。
  3. 文件非常大的时候,多次读取。

🐳Readable可读流:当我们在读取内容的时候还可以暂停readAble.pause()

js 复制代码
const fs = require('fs')
const readAble = fs.createReadStream('./aaa.txt', {
  start: 3, // 从什么地方开始
  end: 8, // 从什么地方结束,包括end结束位置
  highWaterMark: 3 // 每次读完三个输出一次,如果不设置则默认64kb
})
readAble.on('data', (data) => {
  console.log(data.toString())
  readAble.pause() // 暂停一次

  setTimeout(() => {
    readAble.resume() // 两秒钟后恢复读取
  }, 2000)
})

🐻可读流的其他事件

不知道你注意到了没有,在上边我们使用了on进行监听了事件,不知道你思考了没有为什么能够通过on进行监听,这种监听方式不应该是events中的用法吗?是的,确实是events中的用法,在可读流之所以能够因为在可读流中继承了了events所以可以使用它所有的方法,基于这个知识,我们可以看下可读流的其他方法

  1. 通过流将文件打开
js 复制代码
readStream.on('open',(fd)=>{
  console.log("通过流将文件打开")
})
  1. 已经读取到了文件末尾
js 复制代码
readStream.on('end',()=>{
  console.log("已经读取到文件的末尾")
})
  1. 监听文件什么时候读取结束
js 复制代码
readStream.on('close',()=>{
  console.log("文件已经被关闭")
})

三.可写流的基本使用


我们在上述中学习了可读取流,我们知道在fs中我们也可以对文件进行写入,但是像文件读取一样会有文件的一次性读取的问题,所以我们在写入文件的时候一般也会使用写入流来完成。

👹创建一个可写流

js 复制代码
const fs = require("fs")
const writeAble = fs.createWriteStream('./ccc.txt', {
  flag: 'a+',
  start: 5,
})

writeAble.write("HelloWorld") //能够被多次写入调用

🥺写入完成:当写入完成的时候,需要手动去掉close方法

js 复制代码
writeStream.close()

🤡end方法,将最后的内容写入文件中,并且可以关闭文件,所以一般我们很少调用close而是调用end。

js 复制代码
writeStream.end("哈哈哈哈")

四.pip方法的使用


😊在学习pip之前我们首先来写一个小案例,对一个文件通过代码进行拷贝,方法不限

  1. 一次性进行读取和写入操作
js 复制代码
const fs = require("fs")
fs.readFile("./ccc.txt", (err, data) => {
  if (err) return
  fs.writeFile("./ddd.txt", data, () => {
    console.log("文件写入成功")
  })
})
  1. 通过可读流和可写流
js 复制代码
const fs = require("fs")
const readStream = fs.createReadStream("./aaa.txt")
const writeStream = fs.createWriteStream("./foo.txt")
readStream.on("data", (data) => {
  writeStream.write(data)
})
writeStream.on("end", () => {
  writeStream.close()
})
  1. 在可读流和可写流之间建立一个管道pip直接将读取的内容进行写入,这里使用的pip就是管道的意思,其作用就是将可读流的内容直接写入到可写流的文件中。
js 复制代码
const fs = require("fs")
const readAble = fs.createReadStream("./aaa.txt")
const writeAble = fs.createWriteStream("./foocopy.txt")
readAble.pipe(writeAble)

五.总结


🦝我们在本小结学习了的概念,在日常生活中我们提到这个词我们可能会想到小溪,但是在编程中流往往指的是数据流,我们在之前对文件进行操作的时候,我们会使用fs进行一次性的读取或者写入,但是这样的缺点有很多,包括不能进行初始结束位置的控制等等内容,因此我们使用了流来解决这个问题,我们通过可读流,可写流来积进行文件的读取和使用,并且可以通过方法对文件的读写进行监听,除此之外我们还使用了pip方法,来直接通过管道将读取的流直接写入可写的文件中,当然这些内容仅仅是Node中的冰山一角,但是也是我们全栈之路的毕竟之路~

相关推荐
叫我:松哥6 分钟前
基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask
前端·python·随机森林·机器学习·数据分析·flask·bootstrap
让开,我要吃人了9 分钟前
HarmonyOS鸿蒙开发实战(5.0)网格元素拖动交换案例实践
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙开发
谢尔登17 分钟前
Webpack 和 Vite 的区别
前端·webpack·node.js
谢尔登17 分钟前
【Webpack】Tree Shaking
前端·webpack·node.js
过期的H2O233 分钟前
【H2O2|全栈】关于CSS(4)CSS基础(四)
前端·css
纳尼亚awsl1 小时前
无限滚动组件封装(vue+vant)
前端·javascript·vue.js
八了个戒1 小时前
【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」
开发语言·前端·javascript·面试·typescript
西瓜本瓜@1 小时前
React + React Image支持图像的各种转换,如圆形、模糊等效果吗?
前端·react.js·前端框架
黄毛火烧雪下1 小时前
React 的 useEffect 钩子,执行一些异步操作来加载基本信息
前端·chrome·react.js
蓝莓味柯基1 小时前
React——点击事件函数调用问题
前端·javascript·react.js