46 # 可读流 readStream

上一节实现了文件拷贝功能,其中的读和写的操作都耦合在一起了,能不能实现一个方法,可以用一行搞定,这里涉及到流里的 pipe

流是有方向的,先读出来再写,node 中实现了流的模块(stream)

文件也想实现流,所以内部文件系统继承了 stream 模块

createReadStream 创建一个可读流(返回一个可读流对象),这个方法默认并不会读取内容:

const fs = require("fs");
const path = require("path");

// createReadStream(path: fs.PathLike, options?: BufferEncoding | ReadStreamOptions | undefined): fs.ReadStream
// 内部的实现原理还是:fs.open  fs.read  fs.close
let rs = fs.createReadStream(path.resolve(__dirname, "./name.txt"), {
    flags: "r", // r 代表读取
    encoding: null, // 默认 null,就是 buffer 类型的
    mode: 0o666, // 模式:可读可写
    autoClose: true, // fs.close
    start: 0, // 0 - 8 包前又包后
    end: 8,
    highWaterMark: 3 // 每次读取的个数
});
console.log(rs);

46 # 可读流 readStream_第1张图片

为了多个异步方法可以解耦,可以采用发布订阅模式

可读流继承了 events 模块,这里的名字必须要叫 data,源码里写的就是 rs.emit("data"),如果监听了 data,内部会拼命读取文件的内容,触发对应的回调,默认会直到文件读取完毕

下面新建 name.txt 文件,里面添加:

凯小默的博客

46 # 可读流 readStream_第2张图片

在添加下面的事件监听

const fs = require("fs");
const path = require("path");

let rs = fs.createReadStream(path.resolve(__dirname, "./name.txt"), {
    flags: "r", // r 代表读取
    encoding: null, // 默认 null,就是 buffer 类型的
    mode: 0o666, // 模式:可读可写
    autoClose: true, // fs.close
    start: 0, // 0 - 8 包前又包后
    end: 8,
    highWaterMark: 3 // 每次读取的个数
});

let bufferArr = [];
// 监听 open(文件流特殊的事件,普通流没有)
rs.on("open", (fd) => {
    console.log("open---->", fd);
});
// 监听 data
rs.on("data", (data) => {
    console.log("data---->", data);
    bufferArr.push(data);
    // rs.pause 可以让可读流暂停触发 data 事件
    rs.pause();
    console.log("pause---->暂停");
    // 再次触发 data 事件,可以使用 rs.resume
    setTimeout(() => {
        console.log("过 2s 再次触发 data 事件");
        rs.resume();
    }, 2000);
});
// 监听 end
rs.on("end", () => {
    console.log("end---->", Buffer.concat(bufferArr).toString());
});
// 监听 error
rs.on("error", (err) => {
    console.log("err---->", err);
});
// 监听 close (文件流特殊的事件,普通流没有)
rs.on("close", () => {
    console.log("close---->");
});

46 # 可读流 readStream_第3张图片

你可能感兴趣的:(Node,/,Node,框架,前端工程架构,stream)