参考:
1.基本
1.1 概念
Buffer是node自带,挂载全局对象global上,且无需引入
JavaScript 和 c++相结合
主要用来处理网络协议、操作数据库、处理图片、读写文件等需要处理大量二进制数据的场景。
既主要用来操作字节。
1.2 构成
Buffer对象类似于数组,元素为16进制的两位数(0-255,既1个字节byte(8bit)8位二进制包含的范围,2=256个数字)
// v10后,new Buffer 由 Buffer.from代替
let str0 = "窗"
let buf6 = Buffer.from(str0, 'utf-8')
console.log(buf6);
let str1 = "a"
let buf7 = Buffer.from(str1, 'utf-8')
console.log(buf7);
let str2 = "窗a"
let buf8 = Buffer.from(str2, 'utf-8')
console.log(buf8);
不同编码的字符串占用的元素个数不同,在UTF-8中,中文占用3个字符(3字节),字母和标点符合占用一个元素(一个字节)
不同编码参考:
语雀内容
const buf = Buffer.from("1")
console.log(buf);
console.log(buf[0])
const buf2 = Buffer.from("Hi")
console.log(buf2);
console.log(buf2[0])
console.log(buf2[1])
const buf3 = Buffer.from(" ")
console.log(buf3);
console.log(buf3[0])
const buf4 = Buffer.from("ā")
console.log(buf4);
console.log(buf4[0], buf4[1])
参考Unicode码
字符 空格
字符 H 和 i
字符 1
拉丁字母 ā16进制 二进制 之和c4 81 101 ~~196 129 257~~
2 内存分配
Buffer对象内存不在v8,而是在node的c++层面申请的。
Node在内存的使用上应用的是在C++层面申请内存、在JavaScript中分配内存的策略
Node采用了slab,分配机制slab就是一块申请好的固定大小的内存区域
当我们需要一个Buffer对象,可以通过以下方式分配指定大小的Buffer对象:
new Buffer(size);
Node以8 KB为界限来区分Buffer是大对象还是小对象:
Buffer.poolSize = 8 * 1024;
这个8 KB的值也就是每个slab的大小值
总之,
当分配小对象时,优先共用同一个空间够用的slab,容不下时,再创建新的slab
当分配大对象是,则直接分配一个slab空间,单独占用
3 与字符串互转
支持的编码类型
ASCII
UTF-8
UTF-16LE/UCS-2
Base64
Binary
Hex
3.1 字符串转Buffer
3.2 Buffer转字符串
实现Buffer向字符串的转换也十分简单,Buffer对象的toString()可以将Buffer对象转换为字符串,
代码如下:
buf.toString([encoding], [start], [end])
比较精巧的是,可以设置encoding(默认为UTF-8)、start、end这3个参数实现整体或局部的转换。如果Buffer对象由多种编码写入,就需要在局部指定不同的编码,才能转换回正常的编码
3.3 字符串拼接-乱码问题
对于宽字节,比如中文字符,在UTF-8中占用三个字节,那么在Buffer常见的场景Strem中,总是一段一段buffer读取,就会涉及到拼接等问题,很容易出现乱码的问题,具体参考《深入浅出nodejs》
4 性能
网络传输中数据是二进制,所以预先把String转换成Buffer,会明显提高QPS
在Strem中,合理的设置highWaterMark也会提高文件读取速度