文件流 stream
- 什么是流
- 流是指数据的流动,数据从一个地方缓缓的流到另一个地方
- 流是有方向的
- 可读流 Readable:数据从源头流向内存
- 可写流 Writable: 数据从内存流向源头
- 双工流 Duplex: 数据即从源头流向内存又可从内存流向源头
- 转换流 用的比较少
- 为什么需要流
- 其他介质和内存的数据规模不一致 (大小)
- 其他介质和内存数据处理能力不一致 (速度)
- 文件流
- 什么是文件流 内存数据核磁盘文件数据之间的流动
- 文件流的创建
创建文件流
-
创建可读流
fs.createReadStream(path[, options])- 创建一个文件可读流,用于读取文件内容
- path:读取文件路径
- options:
- encoding: "utf-8", // 默认是buffer 数据流
- start: 0, // 数据流 开始的字节
- end: max, // 数据流 结束的字节
- highWaterMark: 6410241024` // 一次传输多少字节
const fs = require("fs")
const path = require("path")
const file = path.resolve(__dirname, "./a.txt")
const rs = fs.createReadStream(file, { // 创建可读 文件流
encoding: "utf-8",
highWaterMark: 2,
autoClose: true // 读完后自动关闭 默认true
})
rs.on("open", () => {
console.log("打开文件");
})
rs.on("data", chunk => {
console.log("读取一部分文件", chunk);
rs.pause()
})
rs.on("pause", () => {
console.log("暂停");
rs.resume()
})
rs.on("error", () => {
console.log("文件读取失败");
})
rs.on("close", () => { // 读取完自动关闭,只有 ondata才会执行
console.log("文件关闭");
})
rs.on("end", () => {
console.log("文件结束");
})
rs.on("ready", () => {
console.log("读取文件");
})
// log 打开文件
读取一部分文件 asdfasfsaf
暂停
文件结束
文件关闭
- 创建文件写入流
fs.createWriteStream(path[, options])- 注意背压问题(当读取速度大于写入速度,或者一次写入 大于 highWaterMark)
- 创建一个文件写入流,用于存入文件内容 如果没有文件会自动创建
- path:读取文件路径
- options:
- flag: w, // w 覆盖 a 追加
- encoding: "utf-8", // 默认是utf-8
- start: 0, // 数据流 开始的字节
- end: max, // 数据流 结束的字节
- highWaterMark: 6410241024` // 一次传输多少字节
时间基本一致
const fs = require("fs")
const path = require("path")
const file = path.resolve(__dirname, "./b.txt")
const ws = fs.createWriteStream(file, {
encoding: "utf-8", // 默认utf-8
highWaterMark: 3 // 一个中文相当于三个字节 如果一次写入过多,则会加入内存队列
})
let flag = ws.write("你") // 返回队列是否空闲 写入数据
ws.on("drain", () => { // 清空队列 时触发
console.log("内存释放");
})
ws.end([chunk[, encoding]][, callback]) // 表示关闭前写入最后一个数据块
// 现在不允许写入更多!
console.log(flag);
readable.pipe(destination[, options])// 将文件复制到另一个文件
// 读取文件 再复制
// 缺点 占内存,运行时间慢
async function fun() {
const from = path.resolve(__dirname, "./first","./a.txt")
const to = path.resolve(__dirname, "./first","./a1.txt")
console.time("方式一")
const content = await fs.promises.readFile(from)
await fs.promises.writeFile(to, content);
console.timeEnd("方式一")
}
// 文件流复制文件 手写
async function fun1() {
const from = path.resolve(__dirname, "./first","./a.txt")
const to = path.resolve(__dirname, "./first","./a2.txt")
console.time("方式二")
const rs = fs.createReadStream(from)
const ws = fs.createWriteStream(to)
rs.on("data", chunk => {
// 读取 速度 或者 字节大 造成 背压
const flag = ws.write(chunk);
if(!flag) {
rs.pause();
}
})
ws.on("drain", () => {
// 当管道清空 ,可以继续写了
rs.resume()
})
console.timeEnd("方式二")
}