今天的文章需要提前了解一下 node
中 fs
模块的相关 api
,不太熟悉的同学可以点这里。
众所周知,
node
中的fs
模块功能大都与文件相关,比如可以通过fs.createReadStream
创建文件可读流,通过fs.createWriteStream
创建文件可写流,还可以通过监听open
、data
、end
、error
、readable
事件对数据进行操作。由于时间有限,今天我们先来实现一下readable
事件功能。
开始之前,先简单介绍一下可读流函数 fs.createReadStream(path[, options])
中各参数所代表的含义,如下所示:
path <string> | <Buffer> | <URL>
创建可读流的路径options <string> | <Object>
可选参数flags <string>
文件读写标识,默认为 rencoding <string>
读取编码格式,默认为 nullfd <integer>
文件描述符,默认为 nullmode <integer>
文件操作权限,默认为 0o666autoClose <boolean>
文件是否自动关闭,默认为 truestart <integer>
文件读取开始位置,默认为 0end <integer>
文件读取结束位置,默认为 InfinityhighWaterMark <integer>
水位线,每次读取长度,默认为 64字节(64 * 1024)
一、创建可读流
首先我们需要实现一个可读流的类,不防定义为 ReadableStream
,该类可以通过 on
函数进行事件监听,所以需要继承 node
中 EventEmitter
类; 当监听 readable
函数时可读取到文件内容,由此得知在构造函数中除了需要定义上面的变量,还需要调用打开文件和第一次读取文件的功能。代码如下:
let fs = require('fs')
let EventEmitter = require('events')
class ReadableStream extends EventEmitter {
constructor(path, options) {
super()
this.path = path
this.flags = options.flags || 'r'
this.encoding = options.encoding || null
this.autoClose = options.autoClose || true
this.highWaterMark = options.highWaterMark || 64 * 1024
this.start = options.start || 0
this.end = options.end || null
this.mode = options.mode || 0o666
// 是否正在读取文件
this.reading = false
// 当len=0时,触发readable事件
this.emitReadable = false
// 缓存中字节的长度
this.len = 0
// 缓存每次读取的内容,格式为[<Buffer />, <Buffer />, ...]
this.arr = []
// 文件读取的位置
this.pos = this.start
// 是否文件全部读取完
this.finished = false
// 打开文件
this.open()
// 判断用户是否监听了readable事件
this.on('newListener', (type) => {
if (type === 'readable') {
// 第一次文件读取
this.read()
}
})
}
}
module.exports = ReadableStream
复制代码
构