Appearance
Buffer
什么是Buffer
- 缓冲区Buffer是暂时存放输入输出数据的一段内存。
- JS语言没有二进制数据类型,而在处理TCP和文件流的时候,必须要处理二进制数据。
- NodeJS提供了一个Buffer对象来提供对二进制数据的操作
- 是一个表示固定内存分配的全局对象,也就是说要放到缓存区中的字节数需要提前确定
- Buffer好比由一个8位字节元素组成的数组,可以有效的在JavasScript中表示二进制数据
什么是字节
- 字节(Byte)是计算机存储时的一种计量单位,一个字节等于8位二进制数
- 一个位就代表一个0或1,每8个位(bit)组成一个字节(Byte)
- 字节是通过网络传输信息的基本单位
- 一个字节最大值十进制数是255(2**8-1)
进制
- 0b 2进制
- 0x 16进制
- 0o 8进制
转为十进制
- 将任意进制字符串转换为十进制
JavaScript
parseInt("11", 2); // 3 2进制转10进制
parseInt("77", 8); // 63 8进制转10进制
parseInt("e7", 16); //231 16进制转10进制
1
2
3
2
3
转其它进制
- 将10进制转换为其它进制字符串
JavaScript
(3).toString(2) // "11" 十进制转2进制
(17).toString(16) // "11" 十进制转16进制
(33).toString(32) // "11" 十提制转32进制
1
2
3
2
3
定义buffer的三种方式
通过长度定义buffer
JavaScript
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
const buf3 = Buffer.allocUnsafe(10);
1
2
3
4
5
6
2
3
4
5
6
通过数组定义buffer
JavaScript
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
1
2
2
正常情况下为0-255之间;
字符串创建
JavaScript
const buf5 = Buffer.from('珠峰培训');
1
buffer常用方法
fill
JavaScript
`buf.fill(value[, offset[, end]][, encoding])`
buffer.fill(0);
1
2
2
write方法
JavaScript
`buf.write(string[, offset[, length]][, encoding])`
let buffer = Buffer.allocUnsafe(6);
buffer.write('珠',0,3,'utf8');
buffer.write('峰',3,3,'utf8'); //珠峰
1
2
3
4
5
2
3
4
5
writeInt8
- 通过指定的
offset
将value
写入到当前 Buffer 中。 - 这个 value 应当是一个有效的有符号的8位整数
JavaScript
`buf.writeInt8(value, offset[, noAssert])`
let buf = Buffer.alloc(4);
buf.writeInt8()
buf.writeInt8(0,0);
buf.writeInt8(16,1);
buf.writeInt8(32,2);
buf.writeInt8(48,3);
console.log(buf);// <Buffer 00 10 20 30>
console.log(buf.readInt8(0));//0
console.log(buf.readInt8(1));//16
console.log(buf.readInt8(2));//32
console.log(buf.readInt8(3));//48
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Little-Endian&Big-Endian
不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序。
- Big-endian:将高序字节存储在起始地址(高位编址)
- Little-endian:将低序字节存储在起始地址(低位编址)
JavaScript
let buffer = Buffer.alloc(4);
buffer.writeInt16BE(2**8,0);//256
console.log(buffer);//<Buffer 01 00 00 00>
console.log(buffer.readInt16BE(0));//256
buffer.writeInt16LE(2**8,2);//256
console.log(buffer);//<Buffer 01 00 00 01>
console.log(buffer.readInt16LE(2));//256
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
toString方法
JavaScript
`buf.toString([encoding[, start[, end]]])`
let buffer = Buffer.from('珠峰架构');
console.log(buffer.toString('utf8',3,6));//峰
1
2
3
4
2
3
4
slice方法
JavaScript
`buf.slice([start[, end]])`
let buffer = Buffer.from('珠峰架构');
let subBuffer = buffer.slice(0,6);
console.log(subBuffer.toString());
1
2
3
4
5
2
3
4
5
截取乱码问题
JavaScript
let {StringDecoder} = require('string_decoder');
let sd = new StringDecoder();
let buffer = Buffer.from('珠峰');
console.log(sd.write(buffer.slice(0,4)));
console.log(sd.write(buffer.slice(4)));
1
2
3
4
5
2
3
4
5
copy方法
- 复制Buffer 把多个buffer拷贝到一个大buffer上
JavaScript
`buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`
let buffer = Buffer.from('珠峰架构');
let subBuffer = Buffer.alloc(6);
buffer.copy(subBuffer,0,0,4);//珠
buffer.copy(subBuffer,3,3,6);//峰
console.log(subBuffer.toString());//珠峰
Buffer.prototype.copy = function(targetBuffer,targetStart,sourceStart,sourceEnd){
for(let i=sourceStart;i<sourceEnd;i++){
targetBuffer[targetStart++] = this[i];
}
}
let buffer = Buffer.from('珠峰');
let subBuffer = Buffer.alloc(6);
buffer.copy(subBuffer,0,0,4);//珠
buffer.copy(subBuffer,3,3,6);//峰
console.log(subBuffer.toString());//珠峰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
concat方法 [#](#t185.6 concat方法)
JavaScript
`Buffer.concat(list[, totalLength])`
let buffer1 = Buffer.from('珠');
let buffer2 = Buffer.from('峰');
let buffer = Buffer.concat([buffer1,buffer2]);
console.log(buffer.toString());
Buffer.concat = function (list) {
let totalLength = list.reduce((len, item) => len + item.length, 0);
if (list.length == 0)
return list[0];
let newBuffer = Buffer.alloc(totalLength);
let pos = 0;
for (let buffer of list) {
for (let byte of buffer) {
newBuffer[pos++] = byte;
}
}
return newBuffer;
}
let buffer1 = Buffer.from('珠');
let buffer2 = Buffer.from('峰');
let buffer = Buffer.concat([buffer1, buffer2]);
console.log(buffer.toString());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
isBuffer
- 判断是否是buffer
JavaScript
Buffer.isBuffer();
1
length
- 获取字节长度(显示是字符串所代表buffer的长度)
JavaScript
let str = '珠峰';
console.log(str.length);//2
let buffer = Buffer.from(str);
console.log(Buffer.byteLength(buffer));//6
1
2
3
4
2
3
4
base64
- Base64是网络上最常见的用于传输8Bit字节码的编码方式之一
- Base64就是一种基于64个可打印字符来表示二进制数据的方法
- Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3_8 = 4_6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节
JavaScript
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('珠');
console.log(r);//54+g
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11