文件 可读流,可写流,双工流

366 阅读2分钟

文件流 stream

  1. 什么是流
    • 流是指数据的流动,数据从一个地方缓缓的流到另一个地方
    • 流是有方向的
      • 可读流 Readable:数据从源头流向内存
      • 可写流 Writable: 数据从内存流向源头
      • 双工流 Duplex: 数据即从源头流向内存又可从内存流向源头
      • 转换流 用的比较少
  2. 为什么需要流
    • 其他介质和内存的数据规模不一致 (大小)
    • 其他介质和内存数据处理能力不一致 (速度)
  3. 文件流
    • 什么是文件流 内存数据核磁盘文件数据之间的流动
    • 文件流的创建

创建文件流

  1. 创建可读流 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
暂停
文件结束
文件关闭
  1. 创建文件写入流 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);
  1. readable.pipe(destination[, options]) // 将文件复制到另一个文件

image.png

image.png

// 读取文件 再复制   
// 缺点 占内存,运行时间慢
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("方式二")
}