目錄 (づ ̄ 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]);
```

## 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