极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node
计算机就是处理 0 和 1,很尴尬的是在引入 TypedArray 之前,JavaScript 没有操作二进制数据流的机制,Buffer 类用一种更适合 Node.js 的方式实现了 Uint8Array API,用于在 TCP 流、文件系统操作等场景处理二进制字节
1 byte = 8 bit
而 Buffer 处理的是字节 , 从 0 开始计数,Buffer 中的 255 标识一个每位都是 1 的字节
Buffer 类的实例类似于 0 到 255 之间的整型数组(其他整数会通过 & 255 操作强制转换到此范围),Buffer 是一个 JavaScript 和 C++ 结合的模块,对象内存不经 V8 分配,而是由 C++ 申请、JavaScript 分配。缓冲区的大小在创建时确定,不能调整。
Buffer 对象实在过于常用,被直接内置到全局变量中,使用时候无需 require 引入
在 Node.js v6 之前都是通过调用构造函数的方式实例化 Buffer,根据参数返回不同结果。处于安全性原因,这种方式在 v6 后的版本中已经被废除,现在提供了三个职责清晰的函数处理实例化 Buffer 的工作
Buffer.from 支持四种参数类型
// 16 进制显示值
const buf1 = Buffer.from(‘test‘, ‘utf-8‘); // <Buffer 74 65 73 74>
const buf2 = Buffer.from(buf1); // <Buffer 74 65 73 74>,buf1 副本,修改 buf2 不会影响 buf1
const buf3 = Buffer.from([256, 2, 3]); // <Buffer 00 02 03>,超过 255 会取模
const arr = new Uint16Array(2);
arr[0] = 5000;
arr[1] = 4000;
// 和 arr 共享内存
const buf4 = Buffer.from(arr.buffer);
console.log(buf4); // <Buffer 88 13 a0 0f>
// 修改 arr
arr[1] = 6000;
console.log(buf4); // <Buffer 88 13 70 17> buf4 也受到影响
const buf = Buffer.from(new String(‘this is a test‘));
// <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>
分配一个大小为 size 字节的新 Buffer,如果 fill 为 undefined,则用 0 填充 Buffer
const buf = Buffer.alloc(5);
console.log(buf); // <Buffer 00 00 00 00 00>
如果指定了 fill,则分配的 Buffer 通过调用 buf.fill(fill)
进行初始化。
const buf = Buffer.alloc(5, ‘a‘);
console.log(buf); // <Buffer 61 61 61 61 61>
分配一个大小为 size 字节的新 Buffer,allocUnsafe 执行速度比 alloc 快,但方法的名字听起来很不安全,确实也不安全
const buf = Buffer.allocUnsafe(10);
console.log(buf); // 打印内容不确定
Buffer 模块会预分配一个内部的大小为 Buffer.poolSize 的 Buffer 实例,作为快速分配的内存池,用于使用 allocUnsafe() 创建新的 Buffer 实例
alloc 永远不会使用内部的 Buffer 池,而 allocUnsafe 在 size 小于或等于 Buffer.poolSize 的一半时将会使用内部的 Buffer池。 当调用 allocUnsafe 时分配的内存段尚未初始化(不归零),这样分配内存速度很块,但分配到的内存片段可能包含旧数据。如果在使用的时候不覆盖这些旧数据就可能造成内存泄露,虽然速度快,尽量避免使用
创建一个大小为 size 字节的新 Buffer,直接通过c++进行内存分配,不会进行旧值填充,当分配的空间小于4KB的时候,allocUnsafe 会直接使用预分配的 Buffer,因此速度比 allocUnsafeSlow 要快,当大于等于4KB的时候二者速度相差无异
Buffer 目前支持以下几种编码格式
Buffer.from(string [, encoding])
字符串转为 Buffer
const buf1 = Buffer.from(‘test‘, ‘utf-8‘); // <Buffer 74 65 73 74>
buf.toString([encoding[, start[, end]]])
Buffer 实例的 toString 方法可以将 Buffer 转为字符串
const buf1 = Buffer.from(‘test‘, ‘utf-8‘);
console.log(buf1.toString()); // test
console.log(buf1.toString(‘hex‘)); // 74657374
Buffer.concat(list[, totalLength]) 方法可以把多个 Buffer 实例拼接为一个 Buffer 实例
const buf1 = Buffer.from(‘a‘);
const buf2 = Buffer.from(‘b‘);
const buf3 = Buffer.from(‘c‘);
const buf = Buffer.concat([buf1, buf2, buf3]);
console.log(buf); // <Buffer 61 62 63>
在 NodeJS 中一个汉字由三个字节表示,如果我们处理中文字符的时候使用了不是3的倍数的字节数就会造成字符拼接乱码问题
const buf = Buffer.from(‘中文字符串!‘);
for(let i = 0; i < buf.length; i+=5){
var b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(b.toString());
}
这样可以看到结果中出现了乱码
使用 string_decoder 模块可以解决这个问题
const StringDecoder = require(‘string_decoder‘).StringDecoder;
const decoder = new StringDecoder(‘utf8‘);
const buf = Buffer.from(‘中文字符串!‘);
for(let i = 0; i < buf.length; i+=5){
var b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(decoder.write(b));
}
StringDecoder 在得到编码后,知道宽字节在 utf-8 下占3个字节,所以在处理末尾不全的字节时,会保留到第二次 write()。目前只能处理UTF-8、Base64 和 UCS-2/UTF-16LE。
还有一些 Buffer 常用的 API,比较简单不用代码示例了
了解了这些内容就可以进入 stream 的学习了
极简 Node.js 入门 - 4.1 stream 学习第一步:Buffer
原文:https://www.cnblogs.com/dolphinX/p/13722472.html