Stream文件流模块以及pipe()进行大文件复制

Stream文件流模块

  • 1.文件流的概念

Node中File System 模块并没有提供一个 copy的方法,但是可以通过读取文件和写入文件的方式实现;
把文件A的内容全部读入Buffer缓冲区,然后再从缓冲区写入文件B,该过程的执行流程图如下:
文件复制流程

缺点:

Buffer缓冲区限制在1GB,这样的操作对于小型的文本文件,没有多大问题,但是对于较大的文件,比如音频,视频文件,如果使用这种方法很容易使内存爆仓.

解决思路:

采用"读一部分,写一部分"方式;不管文件有多大,只要时间允许,总会处理完成.
文件流读写机制
文件A中的数据以流动的形式通过数据管道,然后写入到文件B中
例如: 在网络上观看视频,并不是整个视频都下载好了才播放的,而是下一点播一点.

优点:

接收方可以提前处理,缩短等待时间,提高速度.

  • 2.node的可读流和可写流

Node.js中文件流的操作由Stream模块提供

  • 1>可读流

使用文件流进行文件复制,首先要创建一个可读流(Readable Stream),可读流可以让用户在源文件中分块读取文件中的数据,然后再从可读流中读取数据.创建可读流的语法如下:

fs.createReadStream(path[,options])

说明:由于流是基于EventEmitter的,从流读取数据的最好方法是监听数据事件,并附加一个回调函数

Stream常用事件表:

事件 说明
data 当有数据可读时触发
end 没有更多数据可读时触发
error 在接收和写入过程中发生错误时触发
finish 所有数据已经被写入到底层系统是触发

接下来我们可以结合一个案例演示进一步学习,
创建一个demo文件夹,在文件夹下创建一个input.txt文件,并写入一句话;然后再创建一个read.js文件,代码如下:

/**
 * 从流中读取数据
 */
var fs = require('fs')
var total = ''
// 创建可读流
var readableStream = fs.createReadStream('input.txt')
// 设置编码为utf8
readableStream.setEncoding('UTF8')
// 处理流事件
readableStream.on('data', function (chunk) {
    total += chunk
})
readableStream.on('end', function () {
    console.log(total)
})
readableStream.on('error', function (err) {
    console.log(err.stack)
})
console.log('程序执行完毕!')

打开终端,执行结果如图下:
在这里插入图片描述
可见,数据被成功读取了,由于事件流的操作都是异步的,所以说先输出"程序执行完毕!"

  • 2>可写流

可写流(Writeable Stream)让用户可以写数据到目的地,像可读流一样,也是基于EventEmitter;创建可写流的语法如下:

fs.createWriteStream(path[,options])

write.js

/**
 * 使用文件流进行文件复制
 */
var fs = require('fs')
// 创建可读流
var readableStream = fs.createReadStream('input.txt')
// 创建可写流
var writeableStream = fs.createWriteStream('output.txt')
// 设置编码为utf8
readableStream.setEncoding('UTF8')
// 处理流事件
readableStream.on('data', function (chunk) {
    // 讲独处的数据写入可写流
    writeableStream.write(chunk)
})
readableStream.on('end', function () {
    // 将剩下的数据全部写入,并且关闭写入的文件,停止写入操作
    writeableStream.end()
})
readableStream.on('error', function (err) {
    console.log(err.stack)
})
console.log('程序执行完毕!')

运行结果:
使用文件流复制执行结果
使用文件流复制文件后的目录:
使用文件流复制后文件结构目录
然后,打开output.txt文件,可以看到与input.txt文件内容相同:
复制成功的文件

  • 3.使用pipe()处理大文件

在使用大文件复制的案例中,通过可读流的chunk参数来传递数据,如果把数据比作是水,这个chunk就相当于盆,使用盆来完成水的传递.在可读流中还有一个函数叫pipe(),这个函数是一个很高效的文件处理方式,可以简化之前复制文件的操作,pipe翻译成中文是管子的意思,使用pipe()对文件进行复制就相当于把盆换成管子,通过管子完成数据的读取和写入.
下面通过案例来演示如何使用pipe()处理大文件复制:
pipe.js

/**
 * 使用pipe()进行文件复制
 */
var fs = require('fs')
// 原文件路径
var srcPath = "f:/music-player/demo2/input.txt"
// 目标文件路径
var distPath = "f:music-player/demo2/output.txt"
var readableStream = fs.createReadStream(srcPath)
var writeableStream = fs.createWriteStream(distPath)
// 可以通过使用可读流的函数pipe()接入到可写流中
// pipe()是一种很高效的数据处理方式
if (readableStream.pipe(writeableStream)) {
    console.log('文件复制成功了')
} else {
    console.log('文件复制失败了')
}

打开终端,执行pipe.js,运行结果如下:
pipe.js的运行结果
文件目录:
文件目录
然后,打开output.txt文件,可以看到与input.txt文件内容相同,文件复制成功
文件复制成功

That’s all ~

猜你喜欢

转载自blog.csdn.net/Calla_Lj/article/details/86171958