一次搞定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中的冰山一角,但是也是我们全栈之路的毕竟之路~

相关推荐
To_OC5 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic5 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy5 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志6 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble7 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯8 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜8 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司9 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
kaiking_g9 小时前
vue项目中,静态导入 vs 动态导入 详解
前端·javascript·vue.js
江华森9 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http