文件流

什么是文件流?

数据从一个地方流到另一个地方

 可读流(Readable):外部设备(磁盘,网卡,显卡,打印机等等)  --->>> 内存

 可写流(Writeable):内存  --->>>  外部设备(磁盘,网卡,显卡,打印机等等)

 双工流(Duple):内存  <<<---->>> 外部设备(磁盘,网卡,显卡,打印机等等)

为什么需要流?(节约内存)

  • 外部设备与内存中的数据规模不一致        内存小   外部设备大    如果内存大小只有1G   但从磁盘读2G内   不能一次读完   这时需要流
  • 外部设备与内存处理数据的能力不一致    内存处理数据快   外部设备慢     内存给磁盘写了1G   磁盘可能需要5秒去处理写数据  其他事件就会受到影响这时就需要流
  • 读取或者写入大文件时数据会推挤在内存中,导致效率低(内存数据多,导致执行时间变长)

文件可读流

1.fs.createReadStream(filename,options)   创建可读流   返回一个ReadStream对象

2.ReadStream对象   

const fs = require("fs");
const path = require("path");

const filename = path.resolve(__dirname, "./1.txt");

const rs = fs.createReadStream(filename, {
    encoding: "utf-8",
    highWaterMark: 1, //根据编码格式决定一次读多少  utf-8一次读一个字符
    autoClose: true, //读完自动关闭文件
})

//这些事件都是异步执行的
rs.on("open", () => {
    console.log("打开文件");
})
rs.on("error", () => {
    console.log("出错了!!!"); //文件不存在或读取错误
})
rs.on("close", () => {
    console.log("文件关闭");  //读完关  手动关
})
rs.on("end", () => {
    console.log("文件读完了"); //文件读完触发
})
rs.on("data", (data) => {
    console.log(data)//读文件
    rs.pause();  //暂停读取
})
rs.on("pause", () => { //文件暂停读触发
    console.log("暂停了");
    setTimeout(() => {
        rs.resume() //继续读
    }, 1000)

})
rs.on("resume", () => { //文件恢复读触发
    console.log("恢复了");
})
// rs.close(); //手动关闭文件

文件可写流

1.fs.createWriteStream(filename,options)   创建可写流

2.WriteStream 对象

3.当写入时可能会产生背压问题   由于内存的处理速度远远大于磁盘的写入速度,当从内存写入磁盘数据过多时,磁盘不能及时写入,导致通道拥挤,数据被阻塞在队列中,产生背压问题,消耗内存

 

4.解决背压问题 

let i = 0
function write() {
    let flag = true
    while (i < 1024 * 1024 && flag) {
        flag = ws.write("a");
        i++;
    }
}
write()
ws.on("drain", () => {   //当通道清空时运行
    write()
})

文件复制(对比流与不同读写的区别)

1.普通读写  10mb 文件复制  47ms

//文件复制
async function method1() {  //先全读到内存,再从内存全部写入磁盘  消耗内存
    const from = path.resolve(__dirname, "./1.txt");
    const to = path.resolve(__dirname, "./2.txt");
    console.time("方式一");
    const data = await fs.promises.readFile(from);
    await fs.promises.writeFile(to, data);
    console.timeEnd("方式一");
    console.log("复制完成");
}
method1()

2.文件流   10mb 文件复制  17ms

function method2() {  //利用流 
    const from = path.resolve(__dirname, "./1.txt");
    const to = path.resolve(__dirname, "./3.txt");
    const rs = fs.createReadStream(from);  //一次读64kb
    const ws = fs.createWriteStream(to,{
        autoClose:true,
    });   //一次写16kb

    console.time("方式二");
    rs.on("data", (chunk) => {
        const flag = ws.write(chunk)
        if (!flag) { //如果产生背压
            rs.pause() //暂停读
        }
    })
    ws.on("drain", () => {
        rs.resume() //管道为空时,恢复读
    })
    rs.on("close", () => {
        ws.end();  //关闭写入流
        console.timeEnd("方式二");
        console.log("复制完成");
    })
}
method2()

3.管道    10mb 文件复制  20ms  

function method3() {
    const from = path.resolve(__dirname, "./1.txt");
    const to = path.resolve(__dirname, "./4.txt");
    const rs = fs.createReadStream(from);  //一次读64kb
    const ws = fs.createWriteStream(to);   //一次写16kb
    console.time("管道");
    rs.pipe(ws);   //读取大文件时  与方法二一样 利用流  读取流--->写入流  
    rs.on("close", () => {
        ws.end();  //关闭写入流
        console.timeEnd("管道");
        console.log("复制完成");
    })
}
method3()

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值