Node.js Buffer 和流
Buffer 处理二进制数据,Stream 实现流式传输,是 Node.js 高效 I/O 的核心。
Buffer 基础
创建 Buffer
JavaScript
// 从字符串创建
const buf1 = Buffer.from('hello');
// 指定长度创建
const buf2 = Buffer.alloc(10); // 填充 0
// 不初始化(更快但内容随机)
const buf3 = Buffer.allocUnsafe(10);
// 从数组创建
const buf4 = Buffer.from([1, 2, 3]);
Buffer 操作
JavaScript
const buf = Buffer.from('Hello World');
// 读取/写入
console.log(buf[0]); // 72 (H 的 ASCII)
buf[0] = 104; // 写入
// 转换
console.log(buf.toString()); // Hello World
console.log(buf.toString('hex')); // 48656c6c...
console.log(buf.toJSON()); // { type: 'Buffer', data: [...] }
// 长度
console.log(buf.length); // 11
Buffer 方法
JavaScript
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from(' World');
// 拼接
const buf3 = Buffer.concat([buf1, buf2]);
console.log(buf3.toString()); // Hello World
// 查找
const buf = Buffer.from('Hello World');
console.log(buf.indexOf('World')); // 6
// 切片
const slice = buf.slice(0, 5);
console.log(slice.toString()); // Hello
// 比较
console.log(buf1.equals(buf2)); // false
console.log(buf1.compare(buf2)); // -1
Stream 流
四种流类型
| 类型 | 说明 | 场景 |
|---|---|---|
| Readable | 可读流 | 文件读取、HTTP 请求 |
| Writable | 可写流 | 文件写入、HTTP 响应 |
| Duplex | 双工流 | WebSocket |
| Transform | 转换流 | 压缩、加密 |
可读流 Readable
JavaScript
const fs = require('fs');
// 创建可读流
const rs = fs.createReadStream('./file.txt', {
highWaterMark: 64 * 1024, // 缓冲区大小
encoding: 'utf8'
});
// 事件模式
rs.on('data', (chunk) => {
console.log('收到数据:', chunk.length);
});
rs.on('end', () => {
console.log('读取完成');
});
rs.on('error', (err) => {
console.error('错误:', err);
});
可写流 Writable
JavaScript
const fs = require('fs');
const ws = fs.createWriteStream('./output.txt');
ws.write('第一行\n');
ws.write('第二行\n');
ws.end('结束');
ws.on('finish', () => {
console.log('写入完成');
});
ws.on('error', (err) => {
console.error('写入错误:', err);
});
管道 pipe
JavaScript
const fs = require('fs');
const zlib = require('zlib');
// 文件压缩
fs.createReadStream('./input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('./input.txt.gz'));
// 链式管道
process.stdin
.pipe(process.stdout);
自定义流
JavaScript
const { Transform } = require('stream');
// 转换流
class UpperCase extends Transform {
_transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
}
const upper = new UpperCase();
process.stdin.pipe(upper).pipe(process.stdout);
流与 Buffer 结合
JavaScript
const fs = require('fs');
// 读取流到 Buffer
const chunks = [];
fs.createReadStream('./file.txt')
.on('data', (chunk) => chunks.push(chunk))
.on('end', () => {
const buffer = Buffer.concat(chunks);
console.log(buffer.toString());
});
背压处理
JavaScript
const fs = require('fs');
const rs = fs.createReadStream('./big.file');
const ws = fs.createWriteStream('./copy.file');
rs.on('data', (chunk) => {
const canContinue = ws.write(chunk);
if (!canContinue) {
rs.pause(); // 写入缓冲区满,暂停读取
}
});
ws.on('drain', () => {
rs.resume(); // 缓冲区清空,恢复读取
});
// 或直接使用 pipe(自动处理背压)
rs.pipe(ws);
注意事项
allocUnsafe性能高但可能含敏感数据,谨慎使用pipe自动处理背压和错误- 流的
highWaterMark影响内存使用和性能- 大文件务必使用流,避免一次性加载到内存
要点总结
Buffer.from()创建 Buffer,支持字符串/数组/Buffer- 四种流:Readable、Writable、Duplex、Transform
pipe()连接流,自动处理背压- 监听
data/end/error处理数据流 - 大文件处理使用流,避免内存溢出
📝 发现内容有误?点击此处直接编辑