Stream读写操作

一.理解Stream


很多人第一次接触 Stream(流) 都会觉得抽象、难懂:到底什么是流?流又能用来做什么?

想象一下:你要把一个巨大鱼塘的水全部抽干

现在给你两个工具:

一个小杯子 ,一个抽水机

你会选哪个?

肯定选抽水机,对吧?

因为鱼塘太大了,用杯子一杯一杯舀,根本舀不完,还特别慢、特别占地方;

但抽水机不一样,它可以连续不断、一点一点把水抽走,不用一次性把所有水都装起来,也不会因为水太多而装不下。

这个抽水机 ,就是编程里的 Stream(流)


对应到代码里就是:

  • 以前用 fs 直接一次性读取/写入整个文件 就像用小杯子一次性把一池塘水全装起来
    文件小的时候没问题,但文件一大,内存直接爆掉
  • Stream(流) 就像抽水机 + 水管 ,它会把文件切成一小段一小段源源不断、连续地读取或写入,不用一次性把整个文件加载到内存里。

大文件、视频、日志、网络数据......只要数据量大,都必须用 Stream,Stream 在 Node.js 里,是 EventEmitter 的实例

二.Stream的使用


在Node中很多功能都是基于流的比如Http,API之间的关系如下:

Node中有四种常见的流,但是其实常用的就只有前两个:

Writable :可以向其写入数据的流,例如fs.createWriteStream()

Readable :可以从中读取数据的流,例如fs.createReadStream()

Duplex :同时为Readable和Writable 例如 net.Socket

Transform :Duplex可以在写入和读取数据时修改或转换数据的流 例如zlib.createDeflate()

Readable

js 复制代码
const fs = require("fs");
// 通过流读取文件
const readStream = fs.createReadStream('./aaa.txt',{
    start:3,
    end:20,
    highWaterMark:3
})

// 监听到读取的数据
readStream.on('data',(data)=>{
    console.log(data.toString());
    readStream.pause() // 读取暂停
    setTimeout(()=>{
        readStream.resume(); // 读取恢复
    },2000) 
})

// 监听文件是否打开
readStream.on('open',(fd)=>{
    console.log("通过流将文件打开了~",fd);
})

// 监听文件是否结束,会自动关闭文件流
readStream.on('end',()=>{
    console.log("数据已经读取结束~");
})

// 文件读取结束并且关闭
readStream.on('close',()=>{
    console.log("文件读取完毕并且关闭");
})

Writable

js 复制代码
const fs = require("fs");
// 一次性写入内容
const writeStream = fs.createWriteStream('./ccc.txt',{
    flags:'a+', // 写入方式
    start:0, // 写入位置
    encoding:'utf8', // 编码方式
})

// open事件
writeStream.on('open',(fd)=>{
    console.log("文件已经被打开",fd);
})

// 使用可写流对文件进行写入
writeStream.write('kobe byrant',err=>{
    console.log("写入成功!");
})

writeStream.on('finish',()=>{
    console.log("文件写入完成~");
})

// end方法,将最后的内容写入到文件中,并关闭,涉及两个操作
writeStream.end('hhhhh')

// 当写入完成时候手动调用写入方法
writeStream.close()

pipe方法

js 复制代码
const fs = require('fs');

// 传统拷贝方式
fs.readFile('./foo.txt',(err,data)=>{
    console.log(data);
    fs.writeFile('./ddd.txt',data,{
        flag:'a+'
    },(err,data)=>{
        if(err) return
        console.log(data,"打印数据信息");
    })
})

// 使用可读流和可写流
const readStream = fs.createReadStream('./foo.txt')
const writeStream = fs.createWriteStream('./foo_copy.txt')
readStream.on('data',(data)=>{
    writeStream.write(data)
})

readStream.on('end',()=>{
    writeStream.close()
})

// 使用pip建立管道来进行文件拷贝
readStream.pipe(writeStream)
相关推荐
程序边界8 小时前
lac_agent自愈链路上篇——crontab守护的那些坑与健康检查实战
后端
笨鸟飞不快8 小时前
从 MVC 到 DDD:一次真实的渐进式迁移实录
后端·架构
程序员威哥8 小时前
C#也能玩转YOLO:工业视觉原生推理方案,零Python依赖
后端
kfaino8 小时前
你好,我叫 Prompt——其实,你一直在给 AI 写程序
后端·openai·ai编程
caibixyy8 小时前
springboot+langchain4j实战Day 16 — 混合检索 + Reranker 重排序
后端
Ai拆代码的曹操8 小时前
揭秘"幽灵 CPU":top 抓不到的短命进程,才是真正的 CPU 杀手
后端
IT_陈寒9 小时前
Python里这个赋值坑,连老司机都能翻车
前端·人工智能·后端
唐青枫9 小时前
推荐一个 Zig Web 工程骨架:wing-app
后端
葫芦和十三19 小时前
图解 MongoDB 13|WiredTiger 存储引擎:B-tree、页和 checkpoint 三件套
后端·mongodb·agent
葫芦和十三19 小时前
图解 MongoDB 14|Cache 与淘汰:WiredTiger 的内存治理
后端·mongodb·面试