Node.js学习四(文件流stream)


前言

       在我们学过fs模块后,可以知道读取文件时采用readFile()方法,那么如果文件太大,读取需要很长时间且内存空间有限时要怎么办呢,下面我们来学习一下Node.js中stream的知识。        数据读写可以看作是事件模式(Event)的特例,不断发送的数据块好比一个个的事件。读数据是read事件,写数据是write事件,而数据块是事件附带的信息。Node 为这类情况提供了一个特殊接口stream。

一、Node处理缓存的方式

       “数据流”(stream)是处理系统缓存的一种方式。操作系统采用数据块(chunk)的方式读取数据,每收到一次数据,就存入缓存。Node应用程序有两种缓存的处理方式:

       第一种是等到所有数据接收完毕,一次性从缓存读取,这就是传统的读取文件的方式;这种方式先将数据全部读入内存,然后处理,优点是符合直觉,流程非常自然,缺点是如果遇到大文件,要花很长时间,才能进入数据处理的步骤。

       第二种是采用“数据流”的方式,收到一块数据,就读取一块,即在数据还没有接收完成时,就开始处理它。这种方式每次只读入数据的一小块,像“流水”一样,每当系统读入了一小块数据,就会触发一个事件,发出“新数据块”的信号。应用程序只要监听这个事件,就能掌握数据读取的进展,做出相应处理,这样就提高了程序的性能。

二、什么是Node.js Stream(流)

       我们可以想象一下文件像液体一样流动,在读取时,可以不间断的,将文件往内存里读取一部分,显示一部分,然后把读取的内容删除,继续读取-显示-删除的步骤,这样就会一直有空间来读取完毕比较大的文件。

       Node.js中的官方解释为:流是用于在 Node.js 中处理流数据的抽象接口。 stream 模块提供了用于实现流接口的 API

       Node.js提供了许多流对象。流可以是可读的、可写的、或两者兼而有之。 所有的流都是 EventEmitter 的实例。
要访问 stream 模块:

const stream = require('stream');

stream 模块对于创建新类型的流实例很有用。 通常不需要使用 stream 模块来消费流。

三、stream(流)的类型

Readable - 用于读操作。(例如,fs.createReadStream())
Writable - 用于写操作。(例如,fs.createWriteStream())
Duplex - 用于读取和写入操作。(例如,net.Socket)
Transform - 输出基于输入的地方进行计算的一种双相流,即操作被写入数据,然后读出结果。(例如,zlib.createDeflate())

       每种流都是事件触发器,当某个流被调用时,就会触发,抛出一个事件,常用的事件有:
data事件:表示流中有数据可以读取时触发
end事件:表示流中没有数据可以读取时触发
error事件:读写数据错误时触发
finish事件:数据刷新到底层系统时触发

四、创建可读流

let fs = require('fs');
//创建可读流,使用fs.createReadStream(文件路径)
let readStream = fs.createReadStream('./001.txt');
//设置编码为utf8
readStream.setEncoding('utf8');
//获取数据流
//事件:监听是否有数据流,当有数据流入,自动触发事件
//使用回调函数来获取数据流,把读取的数据放在回调函数的参数中
readStream.on('data',function (chunk){
    console.log(chunk)
});
//事件:监听是否读取结束,当读取结束,自动触发事件
readStream.on('end',function (){
    console.log('读取结束');
})
//事件:监听是否读取错误,当读取发生错误,自动触发事件
readStream.on('error',function (){
    console.log('读取错误');
})

在这里插入图片描述

五、拷贝文件

使用可读流、可写流和管道流来拷贝文件
写入流:fs模块的createWriteStream方法,就可以创建一个写数据的数据流。
管道流:管道是供一个流的输出作为输入到另一个流的机制。它通常被用于从一个流中获取数据,并通过该流输出到另一个流。
举例:把001.txt中的内容写入data.txt中

let fs = require('fs');
//创建可读流
let readStream = fs.createReadStream('./001.txt');
//创建可写流
let writeStream = fs.createWriteStream('./data.txt')
//把读取的流通过管道放入到写入流
readStream.pipe(writeStream);

在这里插入图片描述
在这里插入图片描述
注意:pipe 管道,可以将数据从可读流添加到可写流

六、链式流

       链式是一个机制,一个流的输出连接到另一个流,并创建一个链多流操作。它通常用于管道的操作。例如:使用管道和链接先压缩文件,然后解压缩。

1、压缩文件

const fs = require('fs');
const zlib = require('zlib');
//创建一个读数据的流,然后压缩文件
let readStream = fs.createReadStream('./001.txt')
                   .pipe(zlib.createGzip())
                   .pipe(fs.createWriteStream('./000.zip'));
//事件:监听是否压缩错误
readStream.on('error',function (err){
    console.log('错误');
});

2、解压文件

const fs = require('fs');
const zlib = require('zlib');
//创建一个读数据的流,然后解压缩文件
let readStream = fs.createReadStream('./000.zip')
                   .pipe(zlib.createGunzip())
                   .pipe(fs.createWriteStream('./000.txt'));
//事件:监听是否解压缩错误
readStream.on('error',function (err){
    console.log('错误');
});
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值