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)
相关推荐
IT_陈寒5 小时前
我又被JavaScript的隐式类型转换坑了
前端·人工智能·后端
用户8356290780515 小时前
Python Word 转 PDF 和 PDF 转 Word 指南
后端·python
用户8356290780515 小时前
如何使用 Python 加密和保护 Word 文档
后端·python
他们叫我秃子6 小时前
前端开发转 Go 全栈(五):终于遇到熟人了,Go 的闭包和高阶函数原来这么像 JavaScript
前端·后端·go
SomeB1oody6 小时前
【RustyML入门】2.6. 线性判别分析
开发语言·后端·机器学习·rust·教程
妙码生花6 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十七):AI时代对组件封装的新理解、agInput 统一入口,动态表单预备
前端·后端·go
Yao8066 小时前
SpringAI + Ollama + DeepSeek + RAG 搭建 AI 航线规划系统
后端
大勇前进6 小时前
SQL Server 分页查询多种写法对比:哪种性能最高?
后端
妙码生花6 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十六):附件管理、增加根据文件后缀生成 SVG 文件图标的接口
前端·后端·go
前端Hardy6 小时前
Vue 终于杀进终端界!这个开源项目让 CLI 开发像写网页一样简单
前端·javascript·后端