Buffer缓存区

  • Buffer是内存区域,它表示在V8引擎外部分配置的固定大小的内存区块(无法调整大小); 理论上来讲,前端的JavaScript是无法从代码层面上直接操控内存的,但是在nodejs环境中,我们可以控制一段数据的内存的大小,就是调控Buffer的大小。我们可以将Buffer数据视为一个数组,每一个整数就代表一个数据字节

  • Buffernode中被引入用以帮助开发者操纵处理二进制数据; 对于前端来讲,对于二进制数据的操作的需求是比较少的,大部分情况下,前端只需要处理字符串就可以了,使用JavaScript提供的string对象完全可以应对,但是后端不一样,在后端,我们通常需要读取或操作一些长文本,或者处理前端传过来的图片和大文件等,这些对象都是二进制的, 在这些应用场景中,string就显得力不从心了! 由此引出Buffer!

  • 使用官方网站提供的应用场景就是: 当我们在观看YouTube视频时,红线超过了观看点,也就是下载数据的速度比查看数据的速度快,浏览器就会对数据进行缓冲!

Buffer对比string

  • 下面展示一个案例: 将一段文本的第一个字符变成大写
/* 1. 使用string方法 */
const str = 'hello! world.....'
const new_str = str.replace('h','H')//使用字符串的replace方法替换字符
console.log(new_str);// Hello! world.....
/*
使用字符串的replace方法的确可以实现以上需求,但是存在一个问题就是:
在js中,字符串是不可改变的,所有对字符串的操作都会生成一个全新的字符串
如果这个文本很大,由几百M的话,那么这个操作就会非常的耗时,也非常的占用内存
*/
/* 2. 使用buffer */
// 使用buffer.from方法将字符串转化为buffer数据
const buffer = Buffer.from('hello! world...')// 创建buffer
buffer[0] = 72//替换为大写字母的ascii码
console.log(buffer.toString());// Hello! world.....

/*
使用buffer我们可以使用类似操作数组的方法来操作二进制数据,直接替换对应的数据字节即可
*/

BufferNode中的基本使用

  • Buffernode中的应用非常的广泛,常结合stream(数据流)来进行使用!

创建buffer的三种方法

  1. Buffer.from()
const b1 = Buffer.from('10');//字符串
const b2 = Buffer.from('10', 'utf8');// 指定编码格式
const b3 = Buffer.from([10]);//数组
const b4 = Buffer.from(b3);//buffer

console.log(b1, b2, b3, b4); // <Buffer 31 30> <Buffer 31 30> <Buffer 0a> <Buffer 0a>
  1. Buffer.alloc
/*
Buffer.alloc(size,fill,encoding)
size: 设置buffer大小
fill: 体重到缓冲区的值
encoding: 表示编码格式
*/
const bAlloc1 = Buffer.alloc(5,'','utf-8'); // 创建一个大小为 5 个字节的缓冲区
bAlloc1.write('hello')//使用.write向缓存区中写入数据
console.log(bAlloc1); // <Buffer 68 65 6c 6c 6f>
// 可以使用.toString()方法将数据解析成字符串

/*
Buffer.alloc()返回一个已初始化的 Buffer,可以保证新创建的 Buffer 永远不会包含旧数据。
*/
  1. Buffer.allocUnsafe(不能使之默认值和编码格式,只能设置长度)
const bAllocUnsafe1 = Buffer.allocUnsafe(10);
console.log(bAllocUnsafe1); // <Buffer 49 ae c9 cd 49 1d 00 00 11 4f>

/*
创建一个大小为 size 字节的新的未初始化的 Buffer,由于 Buffer 是未初始化的,
因此分配的内存片段可能包含敏感的旧数据。在 Buffer 内容可读情况下,则可能会泄
露它的旧数据,这个是不安全的,使用时要谨慎。
*/

其他操作:

const buffer = Buffer.from('hello! world...')// 创建buffer
console.log(buffer);//<Buffer 68 65 6c 6c 6f 21 20 77 6f 72 6c 64 2e 2e 2e>

/* 1. 我们可以像操作数据一样通过下标来获取对应的字节数据 */
console.log(buffer[0]);// 104(16进制68)
// 同样可以修改
// buffer[0] = 10
// console.log(buffer[0]);// 10

/* 2. 我们还可以获取buffer长度 */
console.log(buffer.length);// 15字节

/* 3. 我们还可以使用.slice来截取buffer(会同时修改数据源) */
console.log(buffer.slice(0,2));// <Buffer 68 65>
/* 重0位置开始,截取2个字节(slice或生成一个新的buffer对象) */

/* 4. 我们还可以进行buffer遍历操作 */
for( let i of buffer){
// console.log(i);
const buf = Buffer.from([i])//将buffer中的二进制数据转换成buffer数据
console.log(buf.toString());// 成功输出 hello! world...
}

/* 5. 复制操作 */
const buffer2 = Buffer.alloc(15)//首先创建一个对应大小的buffer
buffer.copy(buffer2)// 将buffer复制到buffer2中(顺序调转)
console.log(buffer2);// <Buffer 68 65 6c 6c 6f 21 20 77 6f 72 6c 64 2e 2e 2e>
// console.log(buffer2.toString());// 转为字符串成功输出hello! world...