阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Buffer的创建与操作

Buffer的创建与操作

作者:陈川 阅读数:4376人阅读 分类: Node.js

在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的设计初衷

下一篇:字符编码处理

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌