let fs = require("fs"); // 读取一个不存在的文件 let rs = fs.createReadStream("xxx.js", { highWarterMark: 2 }); let bufArr = []; rs.on("data", data => { bufArr.push(data); }); rs.on("err", err => { console.log(err); }); rs.on("end", () => { console.log(Buffer.concat(bufArr).toString()); }); // { Error: ENOENT: no such file or directory, open '......xxx.js' ......}
5、打开和关闭文件的监听
流的适用性非常广,不只是文件读写,也可以用在 http 中数据的请求和响应上,但是在针对文件读取返回的 rs 上有两个专有的事件用来监听文件的打开与关闭。
open 事件用来监听文件的打开,回调函数在打开文件后执行, close 事件用来监听文件的关闭,如果创建的可读流的 autoClose 为 true ,在自动关闭文件时触发,回调函数在关闭文件后执行。
let fs = require("fs"); let rs = fs.createReadStream("1.txt", { start: 0, end: 3, highWaterMark: 2 }); rs.on("open", () => { console.log("open"); }); rs.on("close", () => { console.log("close"); }); // open
在上面代码我们看出只要创建了可读流就会打开文件触发 open 事件,因为默认为暂停状态,没有对文件进行读取,所以不会关闭文件,即不会触发 close 事件。
let fs = require("fs"); let rs = fs.createReadStream("1.txt", { start: 0, end: 3, hithWaterMark: 2 }); rs.on("open", () => { console.log("open"); }); rs.on("data", data => { console.log(data); }); rs.on("end", () => { console.log("end"); }); rs.on("close", () => { console.log("close"); }); // open // <Buffer 30 31> // <Buffer 32 33> // end // close
从上面例子执行的打印结果可以看出只有开始读取文件并读完后,才会关闭文件并触发 close 事件, end 事件的触发要早于 close 。
可写流
1、createWriteStream 创建可写流
createWriteStream 方法有两个参数,第一个参数是读取文件的路径,第二个参数为 options 选项,其中有七个参数:
w utf8 null 0o666 true 16 * 1024 createWriteStream 返回值为 fs.WriteStream 对象,第一次写入时会真的写入文件中,继续写入,会写入到缓存中。 let fs = require("fs"); // 创建可写流,写入 2.txt 文件 let ws = fs.createWriteStream("2.txt", { start: 0, highWaterMark: 3 });
2、可写流的 write 方法
在可写流中将内容写入文件需要使用 ws 的 write 方法,参数为写入的内容,返回值是一个布尔值,代表 highWaterMark 的值是否足够当前的写入,如果足够,返回 true ,否则返回 false ,换种说法就是写入内容的长度是否超出了 highWaterMark ,超出返回 false 。
let fs = require("fs"); let ws = fs.createWriteSteam("2.txt", { start: 0, highWaterMark: 3 }); let flag1 = ws.write("1"); console.log(flag1); let flag2 = ws.write("2"); console.log(flag2); let flag3 = ws.write("3"); console.log(flag3); // true // true // false
写入不存在的文件时会自动创建文件,如果 start 的值不是 0 ,在写入不存在的文件时默认找不到写入的位置。
3、可写流的 drain 事件
drain 意为 “吸干”,当前写入的内容已经大于等于了 highWaterMark ,会触发 drain 事件,当内容全部从缓存写入文件后,会执行回调函数。
let fs = require("fs"); let ws = fs.createWriteStream("2.txt", { start: 0, highWaterMark: 3 }); let flag1 = ws.write("1"); console.log(flag1); let flag2 = ws.write("2"); console.log(flag2); let flag3 = ws.write("3"); console.log(flag3); ws.on("drain", () => { console.log("吸干"); }); // true // true // false
4、可写流的 end 方法
end 方法传入的参数为最后写入的内容, end 会将缓存未写入的内容清空写入文件,并关闭文件。
let fs = require("fs"); let ws = fs.createWriteStream("2.txt", { start: 0, highWaterMark: 3 }); let flag1 = ws.write("1"); console.log(flag1); let flag2 = ws.write("2"); console.log(flag2); let flag3 = ws.write("3"); console.log(flag3); ws.on("drain", () => { console.log("吸干"); }); ws.end("写完了"); // true // true // false
在调用 end 方法后,即使再次写入的值超出了 highWaterMark 也不会再触发 drain 事件了,此时打开 2.txt 后发现文件中的内容为 "123写完了"。
let fs = require("fs"); let ws = fs.createWriteStream("2.txt", { start: 0, highWaterMark: 3 }); ws.write("1"); ws.end("写完了"); ws.write("2"); // Error [ERR_STREAM_WRITE_AFTER_END]: write after end...