46 # 可读流 readStream

文章介绍了如何在Node.js中使用fs模块的createReadStream创建可读流来读取文件,通过监听data事件实现内容的获取,并通过pause和resume控制数据流动。此外,还提到了流的解耦和事件机制。

上一节实现了文件拷贝功能,其中的读和写的操作都耦合在一起了,能不能实现一个方法,可以用一行搞定,这里涉及到流里的 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);

在这里插入图片描述

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

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

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

凯小默的博客

在这里插入图片描述

在添加下面的事件监听

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---->");
});

在这里插入图片描述

在 Node.js 中,可读流(`createReadStream`)默认是二进制格式,不带编码。这意味着,如果我们直接读取可读流,得到的数据是二进制数据,而不是文本数据。如果需要将可读流转换为文本数据,需要使用 `toString()` 方法或者将可读流通过 `iconv-lite` 或其他编码库进行解码。 例如,如果我们有一个以 UTF-8 编码的文本文件,可以使用以下代码创建可读流,并将其转换为文本数据: ```javascript const fs = require('fs'); const iconv = require('iconv-lite'); const readStream = fs.createReadStream('file.txt'); const chunks = []; readStream.on('data', (chunk) => { chunks.push(chunk); }); readStream.on('end', () => { const buffer = Buffer.concat(chunks); const text = buffer.toString('utf8'); console.log(text); }); ``` 在上面的代码中,我们首先创建了一个可读流,并定义了一个空数组 `chunks`,用于保存从可读流中读取到的数据。然后,我们监听可读流的 'data' 事件,在事件回调函数中将读取到的数据块保存到 `chunks` 数组中。在 'end' 事件中,我们将所有数据块合并成一个 `Buffer` 对象,然后使用 `toString()` 方法将其转换为文本数据,最终输出到控制台。在这个例子中,我们假设文件编码格式为 UTF-8,因此在将 `Buffer` 对象转换为文本数据时,设置编码格式为 'utf8'。如果文件编码格式为其他格式,需要相应地进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凯小默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值