使用nodeJS编写一个行读器,函数接受一个路径,然后我们可以监听newLine事件,当读取到一行时,就会向外发送newLine事件,并把读取的值全部返回,当读取结束的时候,向外发送end事件。
关键点1:如何实现一个一个字节的读取文件,这个就需要利用流了,我们创建一个可读流,并且是paused模式。
关键2:如何判断是否换行了,在不同的操作系统下面这个是不一样的,在window下面是/n/r(回车加换行),mc是/n linux是/r
好了,有了这几点,我们就可以写出代码了。
//函数接受一个路径,然后我们可以监听newLine事件,当读取到一行时,就会向外发送newLine事件,
//当读取结束的时候,向外发送end事件
const NEW_LINE = 0x0a; //换行
const RETURN = 0x0d; //回车
const EventEmitter = require("events");
const fs = require("fs");
const utils = require("util");
function ReadLine(path, config) {
EventEmitter.call(this);
this.rs = fs.createReadStream(path, { //创建流
...config
// highWaterMark: 1 //定义缓存区大小
});
//当新监听某个函数时,就会调用回调
this.on("newListener", function (type, listener) {
if (type === "newLine") { //当监听newLine是就可以读文件了
let char = "";
let buffer = []; //保存一行的字节
this.rs.on("readable", () => {
while ((char=this.rs.read(1)) !== null) { //每次读取一个字节
if (char[0] === RETURN) { //如果等于回车
this.emit("newLine", Buffer.from(buffer)); //因为已经读到结尾了,那么就发送newLine事件
buffer.length = 0; //清0
//因为在window下面,回车后面还有换行,
let nchar = this.rs.read(1);
if (nchar[0] !== NEW_LINE) { //证明不是window系统,那么就是下一行的字符
buffer.push(nchar[0]);
}
} else if (char[0] === NEW_LINE) {
this.emit("newLine", Buffer.from(buffer));
buffer.length = 0; //清0
} else {
buffer.push(char[0]); //保存下来
}
}
})
this.rs.on("end", () => {
//因为最后的一句话可能没有回车和换行
if (buffer.length) this.emit("newLine", Buffer.from(buffer));
buffer.length = 0; //清0
this.emit("end", "读完了");
})
}
})
//使用paused模式
}
utils.inherits(ReadLine, EventEmitter); //继承
module.exports = ReadLine;
const rl = new ReadLine("./1.txt", {
});
rl.on("newLine", (data) => {
console.log(data.toString());
})
rl.on("end", (data) => {
console.log(data);
})
基本实现功能了。