NodeJS文件流

Node.js 的文件流(File Streams)是非常强大且高效的工具,特别适用于处理大文件、流式数据或需要高效文件操作的场景。fs 模块提供了流(Stream)接口,允许你以异步、非阻塞的方式处理文件的读取和写入。

在 Node.js 中,流分为 读流写流,它们的核心是通过流动的方式将数据传输处理,而不是一次性加载整个文件。这能显著减少内存使用并提升性能。

流(Stream)基础

流是一种处理数据的方式,数据是逐步流动的(而不是一次性加载)。流分为四种类型:

  1. Readable Stream:用于读取数据。
  2. Writable Stream:用于写入数据。
  3. Duplex Stream:既可读又可写。
  4. Transform Stream:对数据进行转换。

文件流通常是 ReadableWritable 类型。

🧱 一、文件流的基本概念

在 Node.js 中,文件流主要通过 fs.createReadStream()fs.createWriteStream() 来操作,它们是基于 stream.Readablestream.Writable 的。

1. 读取文件流 - fs.createReadStream()

fs.createReadStream() 用于从文件中读取数据,并将数据以流的形式逐步传输到内存中。这样可以避免一次性加载整个文件,从而减少内存消耗。

语法

js 复制代码
fs.createReadStream(path[, options])
  • path: 文件路径。
  • options: 可选配置项,如编码方式、开始和结束位置等。

以下是 fs.createReadStream(path, options) 的第二个参数(options)的可选配置项总结表:

配置项 类型 默认值 说明
flags string 'r' 文件打开模式,例如 'r' 代表只读
encoding string 或 null null 指定读取数据的编码,如 'utf8',不设则返回 Buffer
fd number null 已打开文件的描述符,避免重复打开
mode number 0o666 设置文件权限(仅在创建时有效)
autoClose boolean true 流结束时是否自动关闭文件
start number 0 从文件的哪个字节开始读取
end number null 读取到哪个字节结束(包含该字节)
highWaterMark number 64 * 1024 每次读取的最大字节数(缓冲区大小)
emitClose boolean false 是否在流关闭时触发 'close' 事件

示例:读取文件流

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

// 创建一个可读流
const readableStream = fs.createReadStream('example.txt', 'utf8');

// 监听 'data' 事件,逐块读取数据
readableStream.on('data', (chunk) => {
  console.log('读取的数据块:', chunk);
});

// 监听 'end' 事件,表示数据读取完成
readableStream.on('end', () => {
  console.log('文件读取完毕');
});

// 监听 'error' 事件,处理可能的错误
readableStream.on('error', (err) => {
  console.error('读取文件时出错:', err);
});
  • 'data' 事件 :每当读取到一个数据块时,data 事件会触发。
  • 'end' 事件:当文件全部读取完成后触发。
  • 'error' 事件:发生错误时触发。

2. 写入文件流 - fs.createWriteStream()

fs.createWriteStream() 用于向文件中写入数据,并将数据以流的方式逐步写入。这种方式特别适合写入大文件或者需要高效写入的场景。

语法

js 复制代码
fs.createWriteStream(path[, options])
  • path: 文件路径。
  • options : 可选配置项,类似于 createReadStream()

以下是 fs.createWriteStream(path, options) 的第二个参数(options)的可选配置项总结表:

配置项 类型 默认值 说明
flags string 'w' 文件打开模式,如 'w' 表示写入,必要时创建文件
encoding string 'utf8' 写入数据时使用的编码
fd number null 已打开的文件描述符,传入时不会再自动打开文件
mode number 0o666 文件权限设置(创建文件时适用)
autoClose boolean true 写入完成或出错时是否自动关闭文件
emitClose boolean false 是否在关闭时触发 'close' 事件
start number undefined 从文件的哪个字节开始写入
highWaterMark number 16 * 1024 内部缓冲区大小,影响 write() 返回值(流控制)

示例:写入文件流

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

// 创建一个可写流
const writableStream = fs.createWriteStream('output.txt');

// 向文件写入数据
writableStream.write('这是第一行内容\n');
writableStream.write('这是第二行内容\n');

// 结束写入,关闭流
writableStream.end('写入完成');

// 监听 'finish' 事件,表示写入完成
writableStream.on('finish', () => {
  console.log('数据成功写入文件');
});

// 监听 'error' 事件,处理写入错误
writableStream.on('error', (err) => {
  console.error('写入文件时出错:', err);
});
  • 'finish' 事件:当所有数据成功写入并且流关闭时触发。
  • 'error' 事件:发生写入错误时触发。

3. ### fs.createReadStreamfs.createWriteStream 事件总结

事件名 触发条件 适用对象 说明
open 文件成功打开 createReadStream / createWriteStream 当文件被打开时触发,返回文件描述符(fd
close 流关闭后触发 createReadStream / createWriteStream 文件流关闭时触发,表示文件不再被使用
data 数据被读取时触发 createReadStream 每次读取数据时触发,data 事件会传递读取到的数据
end 数据读取完毕时触发 createReadStream 当没有更多数据可读取时触发
finish 数据写入完成时触发 createWriteStream 当数据成功写入流并被刷新到文件时触发
drain 内部缓冲区清空后触发 createWriteStream 当缓冲区的写入数据量少于 highWaterMark,且可继续写入时触发(也就是写入时超过了缓冲区, 等缓冲区清空时就会触发,如果缓冲区一直没有撑满,则不会触发)
error 遇到错误时触发 createReadStream / createWriteStream 读取或写入过程发生错误时触发
pipe 流被传递时触发 createReadStream 当流的数据被"管道"传输到另一个流时触发
unpipe 流的管道解除时触发 createReadStream 当流被解除管道时触发

🛠️ 二、流的管道机制:pipe() 方法

Node.js 提供了流的管道机制,利用 .pipe() 方法可以将一个流直接连接到另一个流。这种方式特别适合文件的复制、数据处理等任务。

示例:使用 .pipe() 复制文件

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

// 创建可读流
const readableStream = fs.createReadStream('source.txt');

// 创建可写流
const writableStream = fs.createWriteStream('destination.txt');

// 使用 pipe 直接将源文件的数据流传输到目标文件
readableStream.pipe(writableStream);

// 监听 'finish' 事件,表示复制完成
writableStream.on('finish', () => {
  console.log('文件复制完成');
});

通过 .pipe(),你可以轻松地将数据从一个流传递到另一个流,且自动处理了数据的流动、内存管理等细节。

🧠 三、流的高效处理:缓冲区和背压

1. 背压(Backpressure)

背压是指流速过快时,目标流可能无法及时处理数据的情况。当一个可写流的缓冲区满时,源流会暂停数据的传输,直到目标流有足够空间。这是 Node.js 中流的一个非常重要的特性,有助于避免内存溢出和性能下降。

2. 缓冲区(Buffer)

Node.js 使用缓冲区来处理流中的数据块,缓冲区是一个临时存储区域,用于存储流中的数据块,直到它们被进一步处理。

3. 文件读取写入时产生背压问题以及解决的流程图

相关推荐
电商数据girl27 分钟前
【经验分享】浅谈京东商品SKU接口的技术实现原理
java·开发语言·前端·数据库·经验分享·eclipse·json
Senar43 分钟前
听《富婆KTV》让我学到个新的API
前端·javascript·浏览器
烛阴1 小时前
提升Web爬虫效率的秘密武器:Puppeteer选择器全攻略
前端·javascript·爬虫
hao_wujing2 小时前
Web 连接和跟踪
服务器·前端·javascript
前端小白从0开始2 小时前
前端基础知识CSS系列 - 04(隐藏页面元素的方式和区别)
前端·css
想不到耶2 小时前
Vue3轮播图组件,当前轮播区域有当前图和左右两边图,两边图各显示一半,支持点击跳转和手动滑动切换
开发语言·前端·javascript
萌萌哒草头将军3 小时前
🚀🚀🚀尤雨溪:Vite 和 JavaScript 工具的未来
前端·vue.js·vuex
Fly-ping3 小时前
【前端】cookie和web stroage(localStorage,sessionStorage)的使用方法及区别
前端
我家媳妇儿萌哒哒3 小时前
el-upload 点击上传按钮前先判断条件满足再弹选择文件框
前端·javascript·vue.js