Node.js Buffer 模块
Buffer 是 Node.js 中用于处理二进制数据流的类。在计算机中,所有数据最终都是以二进制形式存储和传输的,Buffer 提供了一种在 Node.js 中高效处理这些原始二进制数据的方式。
你可以把 Buffer 想象成一个固定大小的"容器",专门用来存放原始二进制数据。与 JavaScript 中的普通数组不同,Buffer 分配的是固定大小的内存块,这使得它在处理大量二进制数据时更加高效。
为什么需要 Buffer?
在 Web 开发中,我们经常需要处理各种二进制数据,比如:
- 文件读写操作
- 网络通信中的数据传输
- 图像处理
- 加密解密操作
JavaScript 最初设计时主要用于浏览器中的 DOM 操作,对二进制数据的处理能力有限。Node.js 作为服务器端运行时,需要更强大的二进制数据处理能力,这就是 Buffer 模块存在的原因。
创建 Buffer
在 Node.js 中有几种创建 Buffer 的方式:
1. 使用 Buffer.alloc()
实例
// 创建一个长度为 10 字节的 Buffer,并用 0 填充
const buf1 = Buffer.alloc(10);
console.log(buf1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
const buf1 = Buffer.alloc(10);
console.log(buf1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
2. 使用 Buffer.allocUnsafe()
实例
// 创建一个长度为 10 字节的 Buffer,但不初始化内容
// 可能包含旧数据,所以更快但不太安全
const buf2 = Buffer.allocUnsafe(10);
console.log(buf2); // <Buffer 内容不确定>
// 可能包含旧数据,所以更快但不太安全
const buf2 = Buffer.allocUnsafe(10);
console.log(buf2); // <Buffer 内容不确定>
3. 从数组创建
实例
// 从数组创建 Buffer
const buf3 = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
console.log(buf3); // <Buffer 62 75 66 66 65 72>
const buf3 = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
console.log(buf3); // <Buffer 62 75 66 66 65 72>
4. 从字符串创建
实例
// 从字符串创建 Buffer
const buf4 = Buffer.from('Hello Node.js');
console.log(buf4); // <Buffer 48 65 6c 6c 6f 20 4e 6f 64 65 2e 6a 73>
const buf4 = Buffer.from('Hello Node.js');
console.log(buf4); // <Buffer 48 65 6c 6c 6f 20 4e 6f 64 65 2e 6a 73>
Buffer 的常用方法
写入数据
实例
const buf = Buffer.alloc(5);
// 写入字符串
buf.write('Hello');
console.log(buf); // <Buffer 48 65 6c 6c 6f>
// 写入时指定编码
const buf2 = Buffer.alloc(10);
buf2.write('你好', 'utf8');
console.log(buf2); // <Buffer e4 bd a0 e5 a5 bd 00 00 00 00>
// 写入字符串
buf.write('Hello');
console.log(buf); // <Buffer 48 65 6c 6c 6f>
// 写入时指定编码
const buf2 = Buffer.alloc(10);
buf2.write('你好', 'utf8');
console.log(buf2); // <Buffer e4 bd a0 e5 a5 bd 00 00 00 00>
读取数据
实例
const buf = Buffer.from('Hello World');
// 读取为字符串
console.log(buf.toString()); // Hello World
// 读取部分内容
console.log(buf.toString('utf8', 0, 5)); // Hello
// 读取为字符串
console.log(buf.toString()); // Hello World
// 读取部分内容
console.log(buf.toString('utf8', 0, 5)); // Hello
复制 Buffer
实例
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from('World');
const buf3 = Buffer.alloc(10);
buf1.copy(buf3, 0); // 将 buf1 复制到 buf3 的开头
buf2.copy(buf3, 5); // 将 buf2 复制到 buf3 的第 5 个字节开始的位置
console.log(buf3.toString()); // HelloWorld
const buf2 = Buffer.from('World');
const buf3 = Buffer.alloc(10);
buf1.copy(buf3, 0); // 将 buf1 复制到 buf3 的开头
buf2.copy(buf3, 5); // 将 buf2 复制到 buf3 的第 5 个字节开始的位置
console.log(buf3.toString()); // HelloWorld
拼接 Buffer
实例
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from(' ');
const buf3 = Buffer.from('World');
const result = Buffer.concat([buf1, buf2, buf3]);
console.log(result.toString()); // Hello World
const buf2 = Buffer.from(' ');
const buf3 = Buffer.from('World');
const result = Buffer.concat([buf1, buf2, buf3]);
console.log(result.toString()); // Hello World
Buffer 与字符串
Buffer 和字符串之间可以相互转换,但需要注意编码问题。常见的编码有:
- 'utf8' (默认)
- 'ascii'
- 'base64'
- 'hex'
示例
实例
// 字符串转 Buffer
const str = 'Hello Buffer';
const buf = Buffer.from(str);
// Buffer 转字符串
console.log(buf.toString()); // Hello Buffer
// 使用不同编码
console.log(buf.toString('hex')); // 48656c6c6f20427566666572
console.log(buf.toString('base64')); // SGVsbG8gQnVmZmVy
const str = 'Hello Buffer';
const buf = Buffer.from(str);
// Buffer 转字符串
console.log(buf.toString()); // Hello Buffer
// 使用不同编码
console.log(buf.toString('hex')); // 48656c6c6f20427566666572
console.log(buf.toString('base64')); // SGVsbG8gQnVmZmVy
Buffer 的实际应用
1. 文件操作
实例
const fs = require('fs');
// 读取文件到 Buffer
fs.readFile('example.txt', (err, data) => {
if (err) throw err;
console.log(data); // <Buffer ...>
console.log(data.toString()); // 文件内容
});
// 写入 Buffer 到文件
const content = Buffer.from('Hello File System');
fs.writeFile('output.txt', content, (err) => {
if (err) throw err;
console.log('文件已保存');
});
// 读取文件到 Buffer
fs.readFile('example.txt', (err, data) => {
if (err) throw err;
console.log(data); // <Buffer ...>
console.log(data.toString()); // 文件内容
});
// 写入 Buffer 到文件
const content = Buffer.from('Hello File System');
fs.writeFile('output.txt', content, (err) => {
if (err) throw err;
console.log('文件已保存');
});
2. 网络通信
实例
const http = require('http');
http.createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => {
chunks.push(chunk); // 收集数据块
});
req.on('end', () => {
const body = Buffer.concat(chunks); // 合并所有数据块
console.log(`接收到的数据: ${body.toString()}`);
res.end('数据已接收');
});
}).listen(3000);
http.createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => {
chunks.push(chunk); // 收集数据块
});
req.on('end', () => {
const body = Buffer.concat(chunks); // 合并所有数据块
console.log(`接收到的数据: ${body.toString()}`);
res.end('数据已接收');
});
}).listen(3000);
3. 图像处理
实例
const fs = require('fs');
const sharp = require('sharp');
// 读取图片到 Buffer
fs.readFile('input.jpg', (err, data) => {
if (err) throw err;
// 使用 sharp 处理 Buffer 中的图像数据
sharp(data)
.resize(200, 200)
.toBuffer()
.then(outputBuffer => {
// 将处理后的 Buffer 写入文件
fs.writeFile('output.jpg', outputBuffer, err => {
if (err) throw err;
console.log('图片处理完成');
});
});
});
const sharp = require('sharp');
// 读取图片到 Buffer
fs.readFile('input.jpg', (err, data) => {
if (err) throw err;
// 使用 sharp 处理 Buffer 中的图像数据
sharp(data)
.resize(200, 200)
.toBuffer()
.then(outputBuffer => {
// 将处理后的 Buffer 写入文件
fs.writeFile('output.jpg', outputBuffer, err => {
if (err) throw err;
console.log('图片处理完成');
});
});
});
注意事项
内存管理:Buffer 直接操作内存,分配大 Buffer 会影响应用性能。
安全性:
Buffer.allocUnsafe()
可能包含敏感数据,使用时要注意。编码一致:Buffer 和字符串转换时要确保使用相同的编码。
版本差异:Node.js 旧版本 (v5.x 及之前) 的 Buffer API 与新版本有所不同,建议使用最新 API。
性能考虑:对于大量数据处理,合理使用 Buffer 可以显著提高性能。
Buffer 是 Node.js 中处理二进制数据的核心模块,理解它的工作原理和使用方法对于开发高效、可靠的 Node.js 应用至关重要。
Buffer
模块方法与属性列表
Buffer
是 Node.js 中用于处理二进制数据的核心模块。以下是 Buffer 模块的主要方法和属性:
Buffer 类属性
属性/方法 | 描述 | 版本引入 |
---|---|---|
Buffer.poolSize | 预分配的内部 Buffer 实例大小(字节),可修改 | 0.11.3 |
Buffer.from() | 从字符串、数组或缓冲区创建新 Buffer | 5.10.0 |
Buffer.alloc() | 创建指定大小的已初始化 Buffer | 5.10.0 |
Buffer.allocUnsafe() | 创建指定大小的未初始化 Buffer(更快但不安全) | 5.10.0 |
Buffer.allocUnsafeSlow() | 创建未初始化 Buffer(不使用共享内存池) | 5.12.0 |
Buffer.isBuffer() | 检查对象是否为 Buffer | 0.1.101 |
Buffer.isEncoding() | 检查编码是否有效 | 0.9.1 |
Buffer.concat() | 合并 Buffer 数组 | 0.7.11 |
Buffer.byteLength() | 返回字符串的字节长度 | 0.1.90 |
Buffer.compare() | 比较两个 Buffer | 0.11.13 |
Buffer 实例方法
方法 | 描述 | 版本引入 |
---|---|---|
buf.length | Buffer 的字节长度 | 0.1.90 |
buf.write() | 向 Buffer 写入字符串 | 0.1.90 |
buf.toString() | 将 Buffer 解码为字符串 | 0.1.90 |
buf.toJSON() | 返回 Buffer 的 JSON 表示 | 0.9.2 |
buf.equals() | 比较两个 Buffer 是否相等 | 0.11.13 |
buf.compare() | 比较 Buffer 并返回排序顺序 | 0.11.13 |
buf.copy() | 复制 Buffer 数据 | 0.1.90 |
buf.slice() | 创建 Buffer 的部分视图 | 0.3.0 |
buf.includes() | 检查 Buffer 是否包含值 | 5.3.0 |
buf.indexOf() | 返回值的首次出现位置 | 1.5.0 |
buf.lastIndexOf() | 返回值的最后出现位置 | 6.0.0 |
buf.fill() | 用指定值填充 Buffer | 0.5.0 |
buf.readUIntLE() | 读取无符号小端整数 | 0.5.5 |
buf.readUIntBE() | 读取无符号大端整数 | 0.5.5 |
buf.readIntLE() | 读取有符号小端整数 | 0.11.15 |
buf.readIntBE() | 读取有符号大端整数 | 0.11.15 |
buf.readDoubleBE() | 读取大端64位双精度浮点数 | 0.11.15 |
buf.readDoubleLE() | 读取小端64位双精度浮点数 | 0.11.15 |
buf.readFloatBE() | 读取大端32位浮点数 | 0.11.15 |
buf.readFloatLE() | 读取小端32位浮点数 | 0.11.15 |
buf.writeUIntLE() | 写入无符号小端整数 | 0.5.5 |
buf.writeUIntBE() | 写入无符号大端整数 | 0.5.5 |
buf.writeIntLE() | 写入有符号小端整数 | 0.11.15 |
buf.writeIntBE() | 写入有符号大端整数 | 0.11.15 |
buf.writeDoubleBE() | 写入大端64位双精度浮点数 | 0.11.15 |
buf.writeDoubleLE() | 写入小端64位双精度浮点数 | 0.11.15 |
buf.writeFloatBE() | 写入大端32位浮点数 | 0.11.15 |
buf.writeFloatLE() | 写入小端32位浮点数 | 0.11.15 |
buf.swap16() | 交换16位字节顺序 | 5.10.0 |
buf.swap32() | 交换32位字节顺序 | 5.10.0 |
buf.swap64() | 交换64位字节顺序 | 6.3.0 |
buf.keys() | 创建 Buffer 键的迭代器 | 1.1.0 |
buf.values() | 创建 Buffer 值的迭代器 | 1.1.0 |
buf.entries() | 创建 [index, byte] 迭代器 | 1.1.0 |
编码类型
Buffer 支持的编码类型:
编码 | 描述 |
---|---|
utf8 | 多字节 Unicode 字符 |
utf16le | 2或4字节 Unicode 字符 |
latin1 | ISO-8859-1 |
ascii | 仅7位 ASCII 数据 |
base64 | Base64 编码 |
base64url | URL安全的Base64编码 |
hex | 十六进制编码 |
ucs2 | utf16le 的别名 |
binary | latin1 的别名(已弃用) |
实例
// 创建 Buffer
const buf1 = Buffer.alloc(10); // 初始化归零的 Buffer
const buf2 = Buffer.from('hello'); // 从字符串创建
const buf3 = Buffer.from([1, 2, 3]); // 从数组创建
// 写入和读取
buf1.write('Node.js');
console.log(buf1.toString('utf8', 0, 6)); // 'Node.js'
// 比较 Buffer
const bufA = Buffer.from('A');
const bufB = Buffer.from('B');
console.log(bufA.compare(bufB)); // -1
// 合并 Buffer
const concatBuf = Buffer.concat([bufA, bufB]);
const buf1 = Buffer.alloc(10); // 初始化归零的 Buffer
const buf2 = Buffer.from('hello'); // 从字符串创建
const buf3 = Buffer.from([1, 2, 3]); // 从数组创建
// 写入和读取
buf1.write('Node.js');
console.log(buf1.toString('utf8', 0, 6)); // 'Node.js'
// 比较 Buffer
const bufA = Buffer.from('A');
const bufB = Buffer.from('B');
console.log(bufA.compare(bufB)); // -1
// 合并 Buffer
const concatBuf = Buffer.concat([bufA, bufB]);
点我分享笔记