Buffer的创建与操作
在Node.js中,Buffer类用于处理二进制数据流,尤其在文件操作、网络通信等场景中至关重要。Buffer对象类似于整数数组,但对应V8堆外的原始内存分配,能够高效处理原始数据。
Buffer的创建方式
Buffer可以通过多种方式创建,每种方式适用于不同的场景。以下是常见的创建方法:
1. 使用Buffer.alloc()创建指定大小的Buffer
// 创建一个长度为10字节的Buffer,并用0填充
const buf1 = Buffer.alloc(10);
console.log(buf1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
// 创建一个长度为5的Buffer,不自动填充内容
const buf2 = Buffer.allocUnsafe(5);
console.log(buf2); // 内容不确定,可能包含旧数据
2. 通过Buffer.from()从现有数据创建
// 从字符串创建
const buf3 = Buffer.from('hello world', 'utf8');
console.log(buf3); // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
// 从数组创建
const buf4 = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]);
console.log(buf4.toString()); // "hello"
// 从另一个Buffer创建
const buf5 = Buffer.from(buf4);
3. 使用Buffer.concat()合并多个Buffer
const buf6 = Buffer.from('Hello');
const buf7 = Buffer.from(' ');
const buf8 = Buffer.from('World');
const combined = Buffer.concat([buf6, buf7, buf8]);
console.log(combined.toString()); // "Hello World"
Buffer的常用操作
Buffer提供了丰富的API来操作二进制数据,下面介绍几种常见操作:
1. 写入数据到Buffer
const buf = Buffer.alloc(10);
// 写入字符串
buf.write('Node.js');
console.log(buf.toString()); // "Node.js"
// 指定位置写入
buf.write('123', 7);
console.log(buf.toString()); // "Node.js123"
2. 读取Buffer数据
const buf = Buffer.from('Node.js Buffer');
// 读取指定位置字节
console.log(buf[0]); // 78 (ASCII码'N')
// 转换为字符串
console.log(buf.toString('utf8', 0, 7)); // "Node.js"
// 转换为JSON
console.log(buf.toJSON());
// { type: 'Buffer', data: [78, 111, 100, 101, 46, 106, 115, 32, 66, 117, 102, 102, 101, 114] }
3. 比较Buffer
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('BCD');
const buf3 = Buffer.from('ABC');
console.log(buf1.equals(buf2)); // false
console.log(buf1.equals(buf3)); // true
console.log(Buffer.compare(buf1, buf2)); // -1 (buf1 < buf2)
4. 复制Buffer
const buf1 = Buffer.from('abcdefghij');
const buf2 = Buffer.from('ABCDEF');
buf2.copy(buf1, 2);
console.log(buf1.toString()); // "abABCDEFij"
5. 切片操作
const buf = Buffer.from('Node.js Buffer');
const slice = buf.slice(0, 7);
console.log(slice.toString()); // "Node.js"
Buffer与字符串转换
Buffer与字符串之间的转换需要注意编码问题:
1. 字符串编码
// 使用不同编码创建Buffer
const buf1 = Buffer.from('你好', 'utf8');
const buf2 = Buffer.from('你好', 'utf16le');
console.log(buf1.length); // 6
console.log(buf2.length); // 4
// 转换为不同编码的字符串
console.log(buf1.toString('base64')); // "5L2g5aW9"
console.log(buf2.toString('hex')); // "604f7d59"
2. 处理多字节字符
const buf = Buffer.from('€');
console.log(buf.length); // 3 (UTF-8编码下欧元符号占3字节)
// 错误处理
const partial = Buffer.from([0xE2, 0x82]); // 不完整的UTF-8序列
console.log(partial.toString('utf8')); // "�" (替换字符)
Buffer的性能优化
1. 预分配Buffer
// 不好的做法:频繁创建小Buffer
function badPractice() {
for (let i = 0; i < 1000; i++) {
const buf = Buffer.alloc(10);
// 使用buf...
}
}
// 好的做法:预分配大Buffer
function goodPractice() {
const pool = Buffer.alloc(1000 * 10);
for (let i = 0; i < 1000; i++) {
const buf = pool.slice(i * 10, (i + 1) * 10);
// 使用buf...
}
}
2. 避免内存拷贝
// 不好的做法:不必要的拷贝
const buf1 = Buffer.from('hello');
const buf2 = Buffer.from(buf1); // 创建了新的内存空间
// 好的做法:共享内存
const buf3 = buf1.slice(0, 3); // 共享底层内存
Buffer在文件操作中的应用
1. 读取文件到Buffer
const fs = require('fs');
// 同步读取
const data = fs.readFileSync('example.txt');
console.log(data instanceof Buffer); // true
// 异步读取
fs.readFile('example.txt', (err, data) => {
if (err) throw err;
console.log(data.toString());
});
2. 写入Buffer到文件
const fs = require('fs');
const buf = Buffer.from('Hello File System');
// 同步写入
fs.writeFileSync('output.txt', buf);
// 异步写入
fs.writeFile('output.txt', buf, (err) => {
if (err) throw err;
console.log('写入完成');
});
Buffer在网络通信中的应用
1. HTTP请求中的Buffer
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(`Received ${body.length} bytes`);
res.end('Data received');
});
}).listen(3000);
2. 处理二进制协议
function parseCustomProtocol(buffer) {
const version = buffer.readUInt8(0);
const length = buffer.readUInt16BE(1);
const payload = buffer.slice(3, 3 + length);
return { version, length, payload };
}
const packet = Buffer.from([0x01, 0x00, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f]);
console.log(parseCustomProtocol(packet));
// { version: 1, length: 5, payload: <Buffer 68 65 6c 6c 6f> }
Buffer的安全注意事项
1. 初始化敏感数据
// 不安全的做法:可能泄漏内存中的旧数据
const unsafeBuf = Buffer.allocUnsafe(256);
// 安全的做法:显式填充
const safeBuf = Buffer.alloc(256);
safeBuf.fill(0); // 显式填充0
2. 处理用户输入
// 限制Buffer大小防止内存耗尽
function safeCreateBuffer(input, maxSize = 1024) {
if (input.length > maxSize) {
throw new Error('Input too large');
}
return Buffer.from(input);
}
Buffer与TypedArray的关系
Node.js的Buffer实际上是Uint8Array的子类:
const buf = Buffer.from([1, 2, 3]);
console.log(buf instanceof Uint8Array); // true
// 与TypedArray互操作
const arr = new Uint16Array([1, 2, 3]);
const bufFromArr = Buffer.from(arr.buffer);
console.log(bufFromArr); // <Buffer 01 00 02 00 03 00>
Buffer的编码支持
Node.js Buffer支持多种编码格式:
const buf = Buffer.from('Hello');
console.log(buf.toString('hex')); // "48656c6c6f"
console.log(buf.toString('base64')); // "SGVsbG8="
console.log(buf.toString('utf16le')); // "H e l l o"
console.log(buf.toString('ascii')); // "Hello"
Buffer的迭代操作
Buffer可以使用各种迭代方式:
const buf = Buffer.from([1, 2, 3]);
// for...of迭代
for (const byte of buf) {
console.log(byte);
}
// entries()方法
for (const [index, byte] of buf.entries()) {
console.log(index, byte);
}
// 使用数组方法
buf.forEach((byte, index) => {
console.log(index, byte);
});
Buffer的填充操作
const buf = Buffer.alloc(10);
// 填充整个Buffer
buf.fill('a');
console.log(buf.toString()); // "aaaaaaaaaa"
// 部分填充
buf.fill('b', 3, 6);
console.log(buf.toString()); // "aaabbbaaaa"
// 使用十六进制填充
buf.fill(0x63, 6); // 0x63是'c'的ASCII码
console.log(buf.toString()); // "aaabbbccaa"
Buffer的查找操作
const buf = Buffer.from('This is a buffer example');
// 查找子Buffer
console.log(buf.indexOf('buffer')); // 10
console.log(buf.indexOf(Buffer.from('example'))); // 17
// 从指定位置查找
console.log(buf.indexOf('is', 5)); // 5
// 检查是否包含
console.log(buf.includes('node')); // false
console.log(buf.includes('buffer')); // true
Buffer的静态方法
// 检查是否是Buffer
console.log(Buffer.isBuffer(Buffer.alloc(1))); // true
console.log(Buffer.isBuffer({})); // false
// 获取字节长度
console.log(Buffer.byteLength('你好')); // 6 (UTF-8)
console.log(Buffer.byteLength('€')); // 3
// 比较Buffer
const buf1 = Buffer.from('123');
const buf2 = Buffer.from('456');
console.log(Buffer.compare(buf1, buf2)); // -1
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:Buffer的设计初衷
下一篇:字符编码处理