# 七.buffer
# 1.什么是 Buffer
- 缓冲区 Buffer 是暂时存放输入输出数据的一段内存
- JS 语言没有二进制数据类型,而在处理 TCP 和文件流的时候,必须要处理二进制数据
- NodeJS 提供了一个 Buffer 对象来提供二进制数据的操作
- 是一个表示固定内存分配的全局对象,也就是说要放到缓冲区中的字节数需要提前确定
- Buffer 好比由一个 8 位字节元素组成的数组,可以有效的在 JavaScript 中表示二进制数据
# 2.什么是字节
- 字节(Byte)是计算机存储时的一种计量单位,一个字节等于 8 位二进制数
- 一个位就代表一个 0 或 1,每 8 个位(bit)组成一个字节(Byte)
- 字节是通过网络传输信息的基本单位
- 一个字节最大值十进制数是 255(2**8-1)
# 3.进制
0b 2 进制
0x 16 进制
0o 8 进制
转为十进制
- 将任意进制字符串转换为十进制
parseInt("11", 2) // 3 2进制转10进制 parseInt("77", 8) // 63 8进制转10进制 parseInt("e7", 16) //231 16进制转10进制
1
2
3转其它进制
- 将 10 进制转换为其它进制字符串
;(3).toString(2) // "11" 十进制转2进制 ;(17).toString(16) // "11" 十进制转16进制 ;(33).toString(32) // "11" 十提制转32进制
1
2
3
# 4.buffer 的三种方式
- 通过长度定义 buffer
const buf1 = Buffer.alloc(10)// 创建一个长度为10,且用 0 填充的buffer
const buf2 = Buffer.alloc(10, 1)// 创建一个长度为10,且用0x1填充的buffer
const buf3 = Buffer.allocUnsafe(10)// 创建一个长度为10,且未初始化的buffer
1
2
3
2
3
- 通过数组定义 buffer(正常情况下为 0-255 之间)
const buf4 = Buffer.from([1, 2, 3])// 创建一个包含 [0x1,0x2,0x3]的buffer
1
- 字符串创建
cosnt buf5 = Buffer.from('abc')
1
# 5.常用方法
- fill
buffer.fill(0) // buf.fill(value[, offset[, end]][, encoding])
1
- write
let buffer = Buffer.allocUnsafe(6) // buf.write(string[, offset[, length]][, encoding])
buffer.write("学", 0, 3, "utf8")
buffer.write("习", 3, 3, "utf8")
1
2
3
2
3
writeInt8
- 通过指定的
offset
将value
写入到当前的 Buffer 中 - 这个 value 应当是一个有效的有符号的 8 位整数
let buf = Buffer.alloc(4) buf.writeInt8() buf.writeInt8(0, 0) // buf.writeInt8(value, offset[, noAssert]) 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- 通过指定的
Little-Endian&Big-Endian
不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序
- Big-endian:将高序字节存储在起始地址(高位编址)
- Little-endian:将低序字节存储在起始地址(低位编址)
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
buf.toString([encoding[, start[, end]]])
let buffer = Buffer.from("好好学习")
console.log(buffer.toString("utf8", 3, 6)) // 好
1
2
2
- slice
buf.slice([start[, end]])
let buffer = Buffer.from("好好学习")
let subBuffer = buffer.slice(0, 6)
console.log(subBuffer.toString())
1
2
3
2
3
- 截取乱码问题
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 上
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()) //好好
1
2
3
4
5
2
3
4
5
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- concat
Buffer.concat(list[, totalLength])
let buffer1 = Buffer.from("学")
let buffer2 = Buffer.from("习")
let buffer = Buffer.concat([buffer1, buffer2])
console.log(buffer.toString())
1
2
3
4
2
3
4
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 判断是否是 buffer
Buffer.isBuffer()
1
- 获取字节长度(显示是字符串所代表 buffer 的长度)
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
# 6.base64
- Base64 是网络上最常见的用于传输 8bit 字节码的编码方式之一
- Base64 就是一种基于 64 个可打印字符来表示二进制数据的方法
- Base64 要求把每三个 8bit 的字节转换为四个 6bit 的字节(38 = 46 = 24),然后把 6bit 再添两位高位 0,组成四个 8bit 的字节
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);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
← 六.Encoding 八.fs →