Node.js 编程实战:理解 Buffer 与 Stream

在处理文件、网络请求、图片、音频等二进制数据时,JavaScript 在浏览器端往往依赖 Web API,而在后端环境中,Node.js 则提供了更底层、更高效的数据处理方式。Buffer 与 Stream 是 Node.js 中处理二进制数据的核心机制,它们构成了 Node.js 高性能 I/O 的基础。

本篇文章将从基础概念讲起,帮助你理解两者之间的关系、应用场景以及如何在实际项目中高效使用。


一、为什么 Node.js 需要 Buffer?

JavaScript 本身只提供字符串类型,没有原生的二进制数据结构。然而服务器程序需要处理的很多数据都不是文本,比如:

  • 图片、视频、音频
  • 文件读写
  • 网络传输的二进制内容
  • 压缩包、PDF 等

因此 Node.js 设计了 Buffer,它是一块专门用于存放二进制数据的内存区域,允许以更低层的方式与 I/O 系统交互。

示例:创建一个 Buffer 并写入数据。

js 复制代码
const buf = Buffer.from("Hello");
console.log(buf);  // <Buffer 48 65 6c 6c 6f>

打印出来的是十六进制表示的字节序列。


二、Buffer 的常用操作

1. 创建 Buffer

js 复制代码
Buffer.from("文本内容");      // 从字符串创建
Buffer.alloc(10);             // 分配固定大小的空 Buffer
Buffer.allocUnsafe(10);       // 更快但可能含有旧数据

2. 读取和修改内容

Buffer 就像字节数组:

js 复制代码
const buf = Buffer.from("ABC");
console.log(buf[0]);  // 65
buf[0] = 97;          // 修改为小写字母 a

3. Buffer 转字符串

js 复制代码
buf.toString("utf-8");

Buffer 本质上是二进制与文本之间的桥梁。


三、什么是 Stream?

在处理大文件时,一次性把全部内容读入内存不仅低效,还可能导致崩溃。为了解决这个问题,Node.js 提供了 Stream(流):一种能够持续、分块处理数据的机制。

Stream 的核心特点:

  • 不需一次性加载全部内容
  • 内存使用更低
  • 边读边处理,速度更快
  • 适合大型文件处理、网络传输场景

例如:读取一个 2GB 的视频文件,使用 Stream 能够流式处理,而不是占用 2GB 内存。


四、Node.js Stream 的四种类型

  1. Readable(可读流) 例如:文件读取、网络请求输入

  2. Writable(可写流) 如:文件写入、网络发送

  3. Duplex(双工流) 既可读又可写,如:TCP 连接

  4. Transform(转换流) 在读写过程中处理数据,如:压缩、加密

Stream 是 Node.js 快速处理 I/O 的核心工具。


五、使用 Stream 读取文件

这是最常见的应用场景之一。

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

const rs = fs.createReadStream("input.txt", { encoding: "utf-8" });

rs.on("data", chunk => {
  console.log("读取到:", chunk);
});

rs.on("end", () => {
  console.log("读取完成");
});

文件会被分成多个小段按顺序读取,不会占用大量内存。


六、使用 Stream 写入文件

js 复制代码
const ws = fs.createWriteStream("output.txt");

ws.write("第一行\n");
ws.write("第二行\n");
ws.end("写入结束");

写入流同样是分块写入,避免大文件造成卡顿。


七、流的强大连接方式:pipe()

Stream 最典型的用法就是 管道(pipe)。你可以将一个可读流直接"输送"到可写流。

例如:复制文件

js 复制代码
fs.createReadStream("input.mp4")
  .pipe(fs.createWriteStream("copy.mp4"));

只需一行代码,就能实现高效的数据传输,且非常节省内存。


八、Buffer 与 Stream 的关系

两者并非互相对立,而是密不可分:

  • Stream 负责"流式分段处理"数据
  • Buffer 负责"存储每一段的二进制数据"

Stream 就像水流,Buffer 就像每一杯盛水的容器。 每次 Stream 分发的数据 chunk 本质上就是一个 Buffer。

例如:

js 复制代码
rs.on("data", chunk => {
  console.log(Buffer.isBuffer(chunk));  // true
});

理解这一点有助于你正确处理大数据流。


九、使用 Buffer 处理网络与二进制协议

在 TCP 通信、WebSocket、图像处理时,你会频繁遇到 Buffer。例如:

js 复制代码
socket.on("data", chunk => {
  // chunk 是 Buffer
});

很多底层协议都会用 Buffer 来解析消息结构,如获取长度、类型、内容等。


十、总结

Buffer 与 Stream 是 Node.js 面向 I/O 设计的两大关键机制:

  • Buffer 提供了操作二进制的能力,是文件、网络、加密等场景的基础。
  • Stream 提供了高效处理大规模数据的方式,使 Node.js 能轻松应对大型文件、实时传输等需求。

掌握它们不仅能写出更高性能的程序,还能帮助你理解 Node.js 在底层如何处理数据流动,为后续学习网络模块、文件系统与 HTTP 服务打下扎实基础。


相关推荐
用户8356290780511 小时前
Word 图表自动化:基于 C# 的高效数据可视化方案
后端·c#
火车叼位2 小时前
让 ast-grep 听你的:指定语言解析 Vue/TSX/JSX 全流程
前端·javascript·后端
哈哈老师啊2 小时前
Springboot学生接送服务平台8rzvo(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue图书商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序员爱钓鱼2 小时前
Node.js 编程实战:npm和yarn基础使用
后端·node.js·trae
程序员爱钓鱼3 小时前
Node.js 编程实战:CommonJS 与ES6 模块
后端·node.js·trae
开心猴爷3 小时前
构建可落地的 iOS 性能测试体系,从场景拆解到多工具协同的工程化实践
后端
Java水解3 小时前
常用经典 SQL 语句大全完整版–详解+实例
后端
雨中飘荡的记忆3 小时前
Spring Test详解
java·后端·spring