一. stream 流
之前文件的读写中, 我们用的是readFile和writeFile来进行, stream和这些有什么区别呢?
- 直接读文件无法控制一些细节的操作;
- 比如从什么位置开始读
- 读到某个位置后, 暂停读取, 某个时刻恢复读取等等.
- 或者文件很大, 比如视频之类的, 一次性全部读取并不合适.
在Node中, 很多对象是基于stream来实现的.
- http模块的Request和Response对象;
- process.stdout对象;
- 另外, 所有的stream都是EventEmitter实例 (源码中从events模块导入).
Nodejs中有四种基本流类型:
- Writable: 可以向其中写入数据的流 ( fs.createWriteStream())
- Readable: 可以从其中读取数据的流 (fs.createReadStream())
- Duplex: 同时为Readable和Writable的流 (net.Socket)
- Transform: Duplex可以在写入和读取数据时修改或转换数据的流 (zlib.createDeflate())
一个简单的小例子:
const fs = require("fs");
const reader = fs.createReadStream("./foo.txt", {
start: 3,
end: 10,
highWaterMark: 2,
});
reader.on("data", (data) => {
console.log(data);
reader.pause();
setTimeout(() => {
reader.resume();
}, 1000);
});
reader.on("open", () => {
console.log("文件被打开");
});
reader.on("close", () => {
console.log("文件被关闭");
});
const fs = require("fs");
// 传统的写入方式
// fs.writeFile("./foo.txt", "hello stream", { flag: "a" }, (err) => {
// console.log(err);
// });
// stream的写入方式
const writer = fs.createWriteStream("./bar.txt", {
flags: "a",
start: 0,
});
writer.write("你好wwq", (err) => {
if (err) {
console.log(err);
return;
}
console.log("写入成功");
});
writer.write("我是wwq", (err) => {
console.log("第二次写入");
});
// writer.close();
// write('hello world)
// close() 关闭整个write流
writer.end("hello world");
writer.on("close", () => {
console.log("文件被关闭");
});
const fs = require("fs");
// // 传统写法
// fs.readFile("./bar.txt", (err, data) => {
// fs.writeFile("./baz.txt", data, (err) => {
// console.log(err);
// });
// });
// stream写法
const reader = fs.createReadStream("./foo.txt");
const writer = fs.createWriteStream("./foz.txt");
reader.pipe(writer);
第三个demo是通过pipe函数将读写流放在一起使用, 相比传统写法简单了很多.