目录 (づ ̄ 3 ̄)づ=>
[TOC]
## 什么是Buffer
Buffer是存放输入输出数据的一段内存,这些数据是一个个**字节**并且以16进制的形式表示。
一个字节就是一个英文字母
一个字节等于8位,256种状态,可以表示 0-255,换算成16进制,就是两位数(16\*16=256)
```
console.log(Buffer.from(['moximoxi'); //<Buffer 6d 6f 78 69 6d 6f 78 69>
```
## Buffer方法
### alloc
```
let bf1 = Buffer.alloc(6,11); //第二个参数为填充值,默认为0,第三个为编码
console.log(Buffer.from(['moximoxi'); //<Buffer 6d 6f 78 69 6d 6f 78 69>
### allocUnsafe
### from
>[info] Buffer.from(string[, encoding])
**encoding <string> string 的字符编码。 默认: 'utf8'**
```
console.log(Buffer.from('嘻嘻')); // <Buffer e5 98 bb e5 98 bb>
???->
console.log(Buffer.from([17,'moximoxi',19,0x11,200])); // <Buffer 11 00 13 11 c8> //如果from的是一个数组,数组只能放数字,如果有字符串会被替换成0
```
### write
```
let bf2 = Buffer.alloc(4);
//1.要写的字符串 2.填充的开始索引 3.填充的字节长度 4.编码
bf2.write('嘿嘿',0,3,'utf8');// [x,x,x,0,0,0]
```
### fill
```
let bf2 = Buffer.alloc(4);
//1.填充的值 2.填充的开始索引 3.结束索引
bf2.fill(3,1,3); //[0,3,3,0]
```
### copy
```
/**
* copy 考到哪里
* @param targetBuffer 目标buffer
* @param targetStart 目标的开始
* @param sourceStart 源的开始
* @param sourceEnd 源的结束
*/
var bf3 = Buffer.from('珠峰');
var bf4 = Buffer.from('培训');
var bf5 = Buffer.allocUnsafe(bf3.length+bf4.length);
bf3.copy(bf5,0); //bf3考到bf5
bf4.copy(bf5,6);
console.log(bf5.toString());
```
#### copy实现
```
/**
* copy 实现
* @param targetBuffer
* @param targetStart
* @param sourceStart
* @param sourceEnd
*/
Buffer.prototype.copy2 = function(targetBuffer,targetStart,sourceStart,sourceEnd=this.length){
for(let i= sourceStart;i<sourceEnd;++i){
targetBuffer[targetStart++] = this[i];
}
}
```
### concat
```
/**
* concat 连接buffer
* @param arr 要链接的bff数组
* @param [num]申请的空间,不填为arr的buffer空间综合
*/
console.log(Buffer.concat([bf3,bf4]).toString());
```
#### 用copy方法实现concat
```
Buffer.iConcat = function(list,totalLength){
//将list中传入的buffer集合合并后返回
1.先判断是否传入期望合并后的Buffer的总长度,如果没有则将buffer集合的总长度作为返回Buffer的长度
if (totalLength === undefined) {
totalLength = list.reduce((prev, next) => prev + next.length, 0);
}
2.创建一个Buffer,将其总长度设为totalLength
let Bf = Buffer.alloc(totalLength);
, offset = 0;
3.利用copy方法用新创建的Buffer来装list中的各个子buffer
list.forEach((bf) => {
bf.copy(Bf, offset);
offset += bf.length;
});
4.如果期望的总长度大于实际Buffer长度决定是截取还是填充多余的位置
5.返回
return Bf.slice(0, offset);
}
```
#### 非copy实现
```
/**
* concat 实现
* @param list
* @param total
* @return {*}
*/
Buffer.concat = function(list,total=list.reduce((len,item)=>len+item.length,0)){
if(list.length===1){
return list[0];
}
let result = Buffer.alloc(total);
let index = 0;
for(let buf of list){
for(let b of buf){
if(index<total){
result[index++] = b;
}else{ //如果设定的总长小于所有子bf的总长会走这里
return result;
}
}
}
//如果传入的长度超过所有子bf的总长,以及顺利将所有子bf赋给大bf 会走这里
return result;
}
```
## Buffer字节、机制以及转换
- 一个字节(byte)等于八位(bit),1111 1111(0-255)
- 0?? 0开头表示八进制
- 0x?? 0x开头表示十六进制
- 0b?? 0b开头表示二进制
### Buffer进制转换
> .tostring()
```
//常用来Buffer.from(string)得来的bf进行转换
let bf = Buffer.from('123');
bf.tostring(2); //用二进制进行编码
bf.tostring(8); //用八进制进行编码
//... 依次类推
bt.tostring('base64'); //用base64进行编码
```
### base64
base64编码一个字节只有六位,多余的两位用0补上
可见字符有64个a-zA-Z0-9+/
```
//进制转换
let buf = Buffer.from('珠');
// console.log(buf.toString('base64'));
//base64 如果一个汉字有24位(3个字节) 转换成4个字节 每个字节就6位 不足补0
console.log(buf);
//1.把16进制转化成2进制 toString()
console.log((0xe7).toString(2));
console.log((0x8f).toString(2));
console.log((0xa0).toString(2));
// 00111111=>63
console.log(parseInt('00111001',2));
//标准64只有64个可见字符
// '+/' 'AZaz' '09'
console.log(str[57]+str[56]+str[62]+str[32]);
```
![](https://box.kancloud.cn/d46506ce8b6a660fda52ddd4857cc426_866x653.png)
## Buffer 与 数字
```
ws.write(123456789) //TYPE ERROR
console.log(Buffer.from([1,2,255]));
console.log(Buffer.from('123','base64'))
console.log(Buffer.from('123','utf8'))
let bf = Buffer.alloc(3);
bf.writeInt8(123,0);
console.log(bf)
console.log(bf.readInt8(bf))
console.log(Buffer.from([123]));
//---------------------------------
>>>
<Buffer 01 02 ff>
<Buffer d7 6d>
<Buffer 31 32 33>
<Buffer 7b 00 00>
123
<Buffer 7b>
```
区别在于from的必须是一个数组形式,读的时候可以tostring ,writeInt的时候可以只写入一个数字,但读的时候必须配合readInt