登录
主页
蓝牙基础:JavaScript之ArrayBuffer的用法
2025-08-06
  
796
深数据
`ArrayBuffer` 是 JavaScript 中用于存储原始二进制数据的固定长度缓冲区,是处理二进制数据(如文件、网络通信、设备交互等场景)的基础。它本身无法直接读写数据,需要通过视图(View) 来操作(如 `TypedArray` 或 `DataView`)。
一、基本概念
ArrayBuffer:内存中的一段二进制数据缓冲区,一旦创建,长度不可修改。
视图(View):用于读写 `ArrayBuffer` 中的数据,提供不同的编码格式(如 8位整数、32位浮点数等)。
`TypedArray`:如 `Uint8Array`(无符号8位整数)、`Int16Array`(有符号16位整数)等,适合同类型数据的连续存储。
`DataView`:更灵活的视图,支持对不同位置的数据使用不同类型读写,还可指定字节序(大端/小端)。
二、常用操作
1.创建 ArrayBuffer
通过 `new ArrayBuffer(length)` 创建指定字节长度的缓冲区:
```javascript
// 创建一个 16 字节的缓冲区
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength); // 16(字节长度)
```
2.通过 TypedArray 操作
`TypedArray` 是一组构造函数的统称,不同类型对应不同的数据格式(字节长度、符号位等):
| 类型 | 含义 | 字节长度 | 取值范围 |
|---------------|-----------------------|----------|------------------------------|
| `Uint8Array` | 无符号8位整数 | 1 | 0 ~ 255 |
| `Int8Array` | 有符号8位整数 | 1 | -128 ~ 127 |
| `Uint16Array` | 无符号16位整数 | 2 | 0 ~ 65535 |
| `Int16Array` | 有符号16位整数 | 2 | -32768 ~ 32767 |
| `Uint32Array` | 无符号32位整数 | 4 | 0 ~ 4294967295 |
| `Int32Array` | 有符号32位整数 | 4 | -2147483648 ~ 2147483647 |
| `Float32Array`| 32位浮点数 | 4 | 约 ±3.4e38(精度较低) |
| `Float64Array`| 64位浮点数(双精度) | 8 | 约 ±1.8e308(精度较高) |
示例:用 Uint8Array 读写数据
```javascript
const buffer = new ArrayBuffer(4); // 4字节缓冲区
const uint8View = new Uint8Array(buffer); // 创建视图
// 写入数据(每个元素占1字节)
uint8View[0] = 0x11; // 16进制
uint8View[1] = 0x22;
uint8View[2] = 0x33;
uint8View[3] = 0x44;
console.log(uint8View); // Uint8Array(4) [17, 34, 51, 68]
console.log(uint8View.byteLength); // 4(视图长度=缓冲区长度)
```
示例:同个缓冲区可创建多个视图
```javascript
const buffer = new ArrayBuffer(8);
// 用 Uint32Array 视图写入两个32位整数(每个占4字节)
const uint32View = new Uint32Array(buffer);
uint32View[0] = 0x12345678;
uint32View[1] = 0x87654321;
// 用 Uint8Array 视图查看所有8字节(按字节拆分)
const uint8View = new Uint8Array(buffer);
console.log(uint8View);
// 输出:[120, 86, 52, 18, 33, 67, 101, 135]
// (注:不同设备可能因字节序不同而显示不同)
```
3.通过 DataView 操作
`DataView` 适合处理异构数据(不同类型数据混合存储),且支持指定字节序(`little-endian` 小端 / `big-endian` 大端)。
常用方法:
读:`getUint8(offset)`、`getInt16(offset, littleEndian)`、`getFloat32(offset, littleEndian)` 等
写:`setUint8(offset, value)`、`setInt16(offset, value, littleEndian)`、`setFloat32(offset, value, littleEndian)` 等
示例:用 DataView 读写混合数据
```javascript
const buffer = new ArrayBuffer(10); // 10字节缓冲区
const dataView = new DataView(buffer);
// 偏移量 0:写入一个8位无符号整数(1字节)
dataView.setUint8(0, 0xAB);
// 偏移量 1:写入一个16位有符号整数(2字节),使用小端序
dataView.setInt16(1, -1234, true); // true 表示小端序
// 偏移量 3:写入一个32位浮点数(4字节),使用大端序
dataView.setFloat32(3, 3.1415, false); // false 表示大端序
// 读取数据
console.log(dataView.getUint8(0)); // 171(0xAB的十进制)
console.log(dataView.getInt16(1, true)); // -1234
console.log(dataView.getFloat32(3, false).toFixed(4)); // 3.1415
```
4.常见转换场景
(1)字符串 ↔ ArrayBuffer
```javascript
// 字符串转 ArrayBuffer(UTF-8 编码)
function stringToBuffer(str) {
const encoder = new TextEncoder();
return encoder.encode(str).buffer;
}
// ArrayBuffer 转字符串(UTF-8 解码)
function bufferToString(buffer) {
const decoder = new TextDecoder();
return decoder.decode(buffer);
}
// 示例
const buffer = stringToBuffer(\"hello\");
console.log(buffer.byteLength); // 5(\"hello\"占5字节)
console.log(bufferToString(buffer)); // \"hello\"
```
(2)十六进制字符串 ↔ ArrayBuffer
```javascript
// 十六进制字符串(如 \"A1B2C3\")转 ArrayBuffer
function hexToBuffer(hex) {
// 移除可能的空格或\"0x\"前缀
hex = hex.replace(/\\s|0x/g, \"\");
const length = hex.length / 2;
const buffer = new ArrayBuffer(length);
const view = new Uint8Array(buffer);
for (let i = 0; i < length; i++) {
view[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return buffer;
}
// ArrayBuffer 转十六进制字符串
function bufferToHex(buffer) {
return Array.from(new Uint8Array(buffer))
.map(byte => byte.toString(16).padStart(2, \"0\"))
.join(\"\")
.toUpperCase();
}
// 示例
const buffer = hexToBuffer(\"A1 B2 C3\");
console.log(bufferToHex(buffer)); // \"A1B2C3\"
```
三、实际应用场景
网络通信:处理 TCP/WebSocket 接收的二进制数据。
设备交互:如蓝牙(如微信小程序向蓝牙设备发送指令时,需将指令转为 `ArrayBuffer`)、USB 设备通信。
文件处理:读取本地文件(如通过 `FileReader` 的 `readAsArrayBuffer` 方法)。
加密/解密:密码学算法(如 AES、SHA)通常基于二进制数据操作。
四、注意事项
`ArrayBuffer` 长度固定,如需修改长度,需创建新缓冲区并复制数据(可通过 `TypedArray` 的 `subarray` 或 `slice` 方法)。
字节序(大端/小端)在跨平台通信中需统一,通常设备协议会指定(如蓝牙设备可能要求小端序)。
`TypedArray` 的 `buffer` 属性可获取其关联的 `ArrayBuffer`,便于共享缓冲区。
通过 `ArrayBuffer` 及视图,JavaScript 能高效处理二进制数据,满足底层通信和数据处理需求。
点赞数:2
© 2021 - 现在 杭州极深数据有限公司 版权所有 联系我们 
浙公网安备 33018302001059号  浙ICP备18026513号-1号