JavaScript没有读取或操作二进制数据流的机制。Buffer类被引入作为Node.js API的一部分,使其可以在TCP流或文件系统操作等场景中处理二进制数据流。
在Node.js中,Buffer是用于处理二进制数据的类。它提供了一种在Node.js中处理二进制数据的方式,可以用于处理文件I/O、网络数据、加密算法等场景。Buffer类可以存储任意大小的二进制数据,并提供了一组方法用于对二进制数据进行操作,如读取、写入、拷贝等。
一、二进制数据
计算机存储和表示任何数据时,都会先将其转换为数字表示,再转换为二进制数。下面是一些常用数据类型的转换方式:
- 整数:通过将整数转换为二进制表示。
- 浮点数:使用IEEE 754标准将浮点数转换为二进制表示。
- 字符:通过字符编码(如ASCII、UTF-8等)将字符转换为二进制表示。
- 布尔值:通常使用1表示true,0表示false。
- 对象和数组:通常使用JSON.stringify()方法来将引用数据类型转换为JSON格式的字符串,然后再通过一些方式(例如Blob对象)将字符串转换为二进制数据。
- 图片:常见编码格式,如JPEG、PNG、GIF等,将其转换为二进制数据。这些编码格式会将图片的像素信息、颜色等转换为二进制数据。
- 视频:常见编码格式,如H.264、MPEG-4等,将其转换为二进制数据。视频编码会对视频的每一帧进行压缩和编码,然后将其转换为二进制数据。
- 音频:常见编码格式,如MP3、AAC等,将其转换为二进制数据。音频编码会对音频信号进行压缩和编码,然后将其转换为二进制数据。
二、Stream
在Node.js中,流(stream)就是一系列从A点到B点移动的数据。
完整的说,就是当有一个很大的数据需要传输、搬运时,不需要等待所有的数据都传输完成才开始进行下一步工作,而是会将巨型数据分割成小块(chunks)进行传输。

所以buffer的原始定义中所说的("streams of binary data... in the context of... file system")意思就是说二进制数据在文件系统中的传输。
三、Buffer
在每次数据传输的过程中,会存在一个数据量的问题。所以当数据到达的时间比数据处理的事件快的时候,我们处理数据就需要等待了;反之,如果处理数据的时间比到达的时间快,这一时刻仅仅到达了一小部分数据,那这一小部分数据需要等待剩下的数据填满,然后再送过去统一处理。
这个"等待区域"就是 Buffer。它是电脑上的一个很小的物理地址,一般在RAM中,在这里数据暂时的存储、等待,最后在流(stream)中,发送过去并处理。
等待状态

传输状态

下一次传输

"实例化"举例
1.公交站
可以把整个流(stream)和buffer的配合过程看作一个坐满人发车的公交站。
stream就是公交的行驶过程。
buffer就是公交站台。
乘客可能在不同的时间来到,人流量无法控制,但早到的乘客必须在站台等待,待当前这辆车能满员之后,才会发车;如果乘客到站发现车已经开走,只能在站台等待下一次满员的时候。
Node.js不能控制数据什么时候传输过来,传输速度,就好像公交车站无法控制人流量一样,它只能决定什么时候发送数据。如果时间还不到,那么Node.js就会把数据放入buffer---"等待区域"中,直到buffer满了之后把它们发送出去进行处理。
2.观看视频
当我们在线观看视频的时候,如果网速够快,数据流(stream)就可以足够快,可以让buffer迅速填满然后发送出去处理,然后处理下一个,再发送,再另一个,直到整个stream完成。
但当网络连接很慢的时候,数据流就会变慢,处理完一个buffer的内容后下一个buffer不能立即发送,视频就会暂停,出现等待转圈状态。
四、Buffer的一些基础API
在stream中,Node.js会自动帮你创建buffer之外,你可以创建自己的buffer并操作它。
csharp
// 创建一个大小为10的空buffer
// 这个buffer只能承载10个字节的内容
const buf1 = Buffer.alloc(10);
// 根据内容直接创建buffer
const buf2 = Buffer.from("hello buffer");
创建了之后,就可以操作buffer了
scss
// 检查下buffer的结构
buf1.toJSON()
// { type: 'Buffer', data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }
// 一个空的buffer
buf2.toJSON()
// { type: 'Buffer',data: [ 104, 101, 108, 108, 111, 32, 98, 117, 102, 102, 101, 114 ] }
// the toJSON() 方法可以将数据进行Unicode编码并展示
// 检查buffer的大小
buf1.length // 10
buf2.length //12 根据数据自动盛满并创建
//写入数据到buffer
buf1.write("Buffer really rocks!")
//解码buffer
buf1.toString() // 'Buffer rea'
//哦豁,因为buf1只能承载10个字节的内容,所有多处的东西会被截断
五、ArrayBuffer简介
ArrayBuffer是JavaScript中的内置对象,用于表示通用的、固定长度的原始二进制数据缓冲区。它提供了一种在JavaScript中处理二进制数据的方式,可以用于操作像音频、视频、图像和其他需要原始二进制数据的数据格式。
ArrayBuffer对象本身不能直接操作数据,但可以使用TypedArray视图或DataView对象来操作其内容。
TypeArray有九种如下类型
类型 | 描述 |
---|---|
Int8Array | 8位带符号整数数组 |
Uint8Array | 8位无符号整数数组 |
Uint8ClampedArray | 8位无符号整数数组(无法溢出) |
Int16Array | 16位带符号整数数组 |
Uint16Array | 16位无符号整数数组 |
Int32Array | 32位带符号整数数组 |
Uint32Array | 32位无符号整数数组 |
Float32Array | 32位浮点数数组 |
Float64Array | 64位浮点数数组 |
node 中的 Buffer 就相当于是操作ArrayBuffer的一个视图(TypedArray中 的 Uint8Array ),因为 Buffer 就是通过继承 Uint8Array 实现的
ArrayBuffer的大小在创建时就被固定了,且不能直接修改大小,因此它更适合于固定大小的数据缓冲区。

"实例化"举例
ArrayBuffer就像是一块标本,TypedArray和DataView就像是显微镜操作台,你可以看(读)到这个 ArrayBuffer 但是你需要这些 TypedArray 或 DataView视图来操作这些数据。
六、Buffer、ArrayBuffer比较
Buffer | ArrayBuffer | |
---|---|---|
相同点 | 都可以进行读取、写入和操作二进制数据。 | |
不同点 | Node.js中用于处理二进制数据的对象 | Web平台的标准,用于在浏览器中处理二进制数据 |
提供了更多的方法和功能,如将二进制数据转换为字符串、进行加密解密等 | 只能通过TypedArray视图或DataView对象来操作其内容,更偏向于底层的二进制数据操作 |
总的来说,ArrayBuffer是一段固定连续的二进制数据缓冲区,Buffer是用于NodeJS中用来操作ArrayBuffer的视图。
ArrBuffer转Buffer
使用Buffer.from
ini
const buf = Buffer.from(arrayBuffer.buffer);
Buffer转ArrayBuffer
Buffer的实例维护了一个属性buffer,亦即ArrayBuffer
arduino
const arrayBuffer = buf.buffer
七、附录
Buffer官方文档: Buffer | Node.js v8.17.0 Documentation (nodejs.org)
ArrayBuffer官方文档:ArrayBuffer - JavaScript | MDN (mozilla.org)