1. 什么是Buffer
- 緩沖區(qū)Buffer是暫時(shí)存放輸入輸出數(shù)據(jù)的一段內(nèi)存烹困。
- JS語(yǔ)言沒(méi)有二進(jìn)制數(shù)據(jù)類(lèi)型嘲更,而在處理TCP和文件流的時(shí)候上沐,必須要處理二進(jìn)制數(shù)據(jù)胯努。
- NodeJS提供了一個(gè)Buffer對(duì)象來(lái)提供對(duì)二進(jìn)制數(shù)據(jù)的操作
- 是一個(gè)表示固定內(nèi)存分配的全局對(duì)象纤勒,也就是說(shuō)要放到緩存區(qū)中的字節(jié)數(shù)需要提前確定
- Buffer好比由一個(gè)8位字節(jié)元素組成的數(shù)組泛鸟,可以有效的在JavasScript中表示二進(jìn)制數(shù)據(jù)
2. 什么是字節(jié)
- 字節(jié)(Byte)是計(jì)算機(jī)存儲(chǔ)時(shí)的一種計(jì)量單位,一個(gè)字節(jié)等于8位二進(jìn)制數(shù)
- 一個(gè)位就代表一個(gè)0或1踊东,每8個(gè)位(bit)組成一個(gè)字節(jié)(Byte)
- 字節(jié)是通過(guò)網(wǎng)絡(luò)傳輸信息的單位
- 一個(gè)字節(jié)最大值十進(jìn)制數(shù)是255
2**8-1;
進(jìn)制
0b 2進(jìn)制
0x 16進(jìn)制
0o 8進(jìn)制
-
將任意進(jìn)制字符串轉(zhuǎn)換為十進(jìn)制
- parseInt("11", 2); // 3 2進(jìn)制轉(zhuǎn)10進(jìn)制
- parseInt("77", 8); // 63 8進(jìn)制轉(zhuǎn)10進(jìn)制
- parseInt("e7", 16); //175 16進(jìn)制轉(zhuǎn)10進(jìn)制
-
將10進(jìn)制轉(zhuǎn)換為其它進(jìn)制字符串
- (3).toString(2)) // "11" 十進(jìn)制轉(zhuǎn)2進(jìn)制
- (17).toString(16) // "11" 十進(jìn)制轉(zhuǎn)16進(jìn)制
- (33).toString(32) // "11" 十提制轉(zhuǎn)32進(jìn)制
3. 定義buffer的三種方式
3.1 通過(guò)長(zhǎng)度定義buffer
// 創(chuàng)建一個(gè)長(zhǎng)度為 10北滥、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 創(chuàng)建一個(gè)長(zhǎng)度為 10闸翅、且用 0x1 填充的 Buffer再芋。
const buf2 = Buffer.alloc(10, 1);
// 創(chuàng)建一個(gè)長(zhǎng)度為 10、且未初始化的 Buffer坚冀。
const buf3 = Buffer.allocUnsafe(10);
3.2 通過(guò)數(shù)組定義buffer
// 創(chuàng)建一個(gè)包含 [0x1, 0x2, 0x3] 的 Buffer济赎。
const buf4 = Buffer.from([1, 2, 3]);
正常情況下為0-255之間;
3.3 字符串創(chuàng)建
const buf5 = Buffer.from('張熙沐楓');
4.buffer常用方法
4.1 buf.fill(value[, offset[, end]][, encoding])
手動(dòng)初始化,擦干凈桌子,將buffer內(nèi)容清0
buffer.fill(0);
4.2 write方法
buf.write(string[, offset[, length]][, encoding])
buffer.write('沐',0,3,'utf8');
buffer.write('楓',3,3,'utf8'); //沐楓
4.3 writeInt8
var buf = new Buffer(4);
buf.writeInt8(0,0);
buf.writeInt8(16,1);
buf.writeInt8(32,2);
buf.writeInt8(48,3);//16*3*/
console.log(buf);
console.log(buf.readInt8(0));
console.log(buf.readInt8(1));
console.log(buf.readInt8(2));
console.log(buf.readInt8(3));
4.3.1 Little-Endian&Big-Endian
不同的CPU有不同的字節(jié)序類(lèi)型,這些字節(jié)序是指整數(shù)在內(nèi)存中保存的順序。
Big-endian:將高序字節(jié)存儲(chǔ)在起始地址(高位編址)
-
Little-endian:將低序字節(jié)存儲(chǔ)在起始地址(低位編址)
let buf3 = new Buffer(4); buf3.writeInt16BE(2**8,0); console.log(buf3);//<Buffer 01 00 00 00> console.log(buf3.readInt16BE(0)); buf3.writeInt16LE(2**8,2); console.log(buf3);//<Buffer 01 00 00 01> console.log(buf3.readInt16LE(2));
4.3 toString方法
buf.toString([encoding[, start[, end]]])
buffer.toString('utf8',3,6)
4.4 slice方法 [#](#t134.4 slice方法)
buf.slice([start[, end]])
let newBuf = buffer.slice(0,4);
4.4.1 截取亂碼問(wèn)題
let {StringDecoder} = require('string_decoder');
let sd = new StringDecoder();
let buffer = new Buffer('沐楓');
console.log(sd.write(buffer.slice(0,4)));
console.log(sd.write(buffer.slice(4)));
4.5 copy方法
復(fù)制Buffer 把多個(gè)buffer拷貝到一個(gè)大buffer上
buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
let buf5 = Buffer.from('張熙沐楓');
let buf6 = Buffer.alloc(6);
buf5.copy(buf6,0,0,4);
buf5.copy(buf6,3,3,6);
//buf6=沐楓
Buffer.prototype.copy2 = function(targetBuffer,targetStart,sourceStart,sourceEnd){
for(let i=sourceStart;i<sourceEnd;i++){
target[targetStart+i] = this[i];
}
}
4.6 concat方法
Buffer.concat(list[, totalLength])
let buf1 = Buffer.from('沐');
let buf2 = Buffer.from('楓');
let buf3 = Buffer.concat([buf1,buf2],3);
console.log(buf3.toString());
Buffer.concat2 = function (list = [], total = list.reduce((len, item) => len + item.length, 0)) {
if (list.length == 1)
return list[0];
let result = Buffer.alloc(total);
let pos = 0;
for (let bf of list) {
for (let b of bf) {
if (pos < total)
result[pos++] = b;
else
return result;
}
}
return result;
}
Buffer.myConcat = function(list,totalLength=list.reduce((len,item)=>len+item.length,0)){
if(list.length==0)
return list[0];
let newBuffer = Buffer.alloc(totalLength);
let offset = 0;
for(let i=0;i<list.length;i++){
if(offset+list[i].length>totalLength){
list[i].copy(newBuffer,offset,0,totalLength-offset);
break;
}else{
list[i].copy(newBuffer,offset,0,list[i].length);
offset+=list[i].length;
}
}
return newBuffer;
}
4.7 isBuffer
判斷是否是buffer
Buffer.isBuffer
4.8 length
獲取字節(jié)長(zhǎng)度(顯示是字符串所代表buffer的長(zhǎng)度)
Buffer.byteLength("沐楓");
buffer.length;
6. base64
Base64是網(wǎng)絡(luò)上最常見(jiàn)的用于傳輸8Bit字節(jié)碼的編碼方式之一司训,Base64就是一種基于64個(gè)可打印字符來(lái)表示二進(jìn)制數(shù)據(jù)的方法构捡。
-
Base64要求把每三個(gè)8Bit的字節(jié)轉(zhuǎn)換為四個(gè)6Bit的字節(jié)(3_8 = 4_6 = 24),然后把6Bit再添兩位高位0壳猜,組成四個(gè)8Bit的字節(jié)勾徽,也就是說(shuō),轉(zhuǎn)換后的字符串理論上將要比原來(lái)的長(zhǎng)1/3
const CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; function transfer(str){ let buf = Buffer.from(str); let result = ''; for(let b of buf){ result += b.toString(2); } return result.match(/(\d{6})/g).map(val=>parseInt(val,2)).map(val=>CHARTS[val]).join(''); } let r = transfer('珠');//54+g