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. 文件读取写入时产生背压问题以及解决的流程图

相关推荐
fanruitian1 小时前
uniapp android开发 测试板本与发行版本
前端·javascript·uni-app
rayufo1 小时前
【工具】列出指定文件夹下所有的目录和文件
开发语言·前端·python
RANCE_atttackkk1 小时前
[Java]实现使用邮箱找回密码的功能
java·开发语言·前端·spring boot·intellij-idea·idea
2501_944525542 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
李白你好3 小时前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
刘一说4 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
徐同保5 小时前
React useRef 完全指南:在异步回调中访问最新的 props/state引言
前端·javascript·react.js
刘一说6 小时前
Vue 导航守卫未生效问题解析:为什么路由守卫不执行或逻辑失效?
前端·javascript·vue.js
一周七喜h6 小时前
在Vue3和TypeScripts中使用pinia
前端·javascript·vue.js
weixin_395448916 小时前
main.c_cursor_0202
前端·网络·算法