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)
相关推荐
妖孽白YoonA1 小时前
xlt-token v1.0.0 正式发布:NestJS / Express 一包接入的 Token 鉴权库
后端·node.js·nestjs
Oo_行者_oO1 小时前
Spring Authorization Server 下 Token 刷新流程自定义实现
后端·面试
alwaysrun1 小时前
C++之灵活易用的YAML解析库yaml-cpp
c++·后端·程序员
pe7er1 小时前
AI为啥会写出if(obj != null && obj.ifEnabled)这样的代码
前端·后端·架构
狗凯之家源码网1 小时前
电商代付系统从零搭建与实战指南
前端·后端·开源
IT_陈寒1 小时前
Vue组件通信这个坑我跳了两次才知道怎么爬出来
前端·人工智能·后端
copyer_xyf2 小时前
Python 文件基本操作
前端·后端·python
西凉的悲伤2 小时前
Spring Security + JWT 登录认证完整实践指南
java·后端·spring·spring security·jwt
砍材农夫2 小时前
物联网实战:Spring Boot MQTT | 客户端框架比对
spring boot·后端·物联网