【HarmonyOS NEXT】鸿蒙 ArrayBuffer 和 Uint8Array 互相转换
前言
在 HarmonyOS NEXT 开发过程中,无论是:
- HTTP 请求
- WebSocket
- TCP/UDP Socket
- MQTT
- 文件读写
- 图片处理
- AES/RSA 加解密
- Base64 编解码
- protobuf
- 蓝牙(BLE)
都会频繁接触两个二进制数据对象:
- ArrayBuffer
- Uint8Array
很多开发者刚开始容易混淆:
为什么接口返回的是 ArrayBuffer?
为什么加密接口要求 Uint8Array?
为什么 HTTP 下载的是 ArrayBuffer,而我要转成 Uint8Array?
二者有什么区别?
实际上:
ArrayBuffer 是内存本体,Uint8Array 是操作内存的视图(View)。
本文将全面讲解二者关系、区别、互转方式、底层原理及实际开发案例。
一、什么是 ArrayBuffer
官方定义:
ArrayBuffer 表示一块固定长度的原始二进制数据。
可以理解成:
内存:
+------------------------------------------------+
| 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF |
+------------------------------------------------+
ArrayBuffer:
- 不知道里面是什么
- 不知道每个字节代表什么
- 只是保存一块连续内存
例如:
let buffer = new ArrayBuffer(8)
表示:
buffer
ByteLength = 8
+----+----+----+----+----+----+----+----+
|00 |00 |00 |00 |00 |00 |00 |00 |
+----+----+----+----+----+----+----+----+
二、什么是 Uint8Array
Uint8Array 是:
ArrayBuffer 的一个"视图(View)"
可以理解成:
ArrayBuffer
+--------------------------------------+
|00|11|22|33|44|55|66|77|
+--------------------------------------+
↑
Uint8Array
它负责:
- 读取数据
- 修改数据
- 遍历数据
例如:
let buffer = new ArrayBuffer(8)
let uint8 = new Uint8Array(buffer)
此时:
buffer
↑
Uint8Array
二者共用同一块内存。
三、为什么需要 Uint8Array
ArrayBuffer 不能直接操作。
例如:
错误:
buffer[0]
不能。
错误:
buffer[1] = 100
不能。
因为:
ArrayBuffer
只是内存
真正操作:
Uint8Array
负责:
buffer[0]
buffer[1]
例如:
let uint8 = new Uint8Array(buffer)
uint8[0] = 10
uint8[1] = 20
四、ArrayBuffer 转 Uint8Array
这是最常见转换。
语法:
let uint8 = new Uint8Array(buffer)
示例:
let buffer = new ArrayBuffer(5)
let uint8 = new Uint8Array(buffer)
uint8[0] = 10
uint8[1] = 20
uint8[2] = 30
uint8[3] = 40
uint8[4] = 50
console.info(uint8)
输出:
10
20
30
40
50
整个过程:
ArrayBuffer
↓
Uint8Array(buffer)
↓
可以读写
五、Uint8Array 转 ArrayBuffer
其实:
不用转换。
因为:
Uint8Array 自带:
buffer
例如:
let uint8 = new Uint8Array(5)
let buffer = uint8.buffer
即可获得:
ArrayBuffer
完整示例:
let uint8 = new Uint8Array([1,2,3,4])
let buffer = uint8.buffer
console.info(buffer.byteLength)
输出:
4
六、验证二者共享内存
示例:
let buffer = new ArrayBuffer(4)
let array = new Uint8Array(buffer)
array[0] = 100
console.info(array[0])
输出:
100
继续:
let array2 = new Uint8Array(buffer)
console.info(array2[0])
输出:
100
说明:
buffer
↑
array
↑
array2
共享同一块内存。
七、修改 Uint8Array 是否影响 ArrayBuffer
会。
示例:
let buffer = new ArrayBuffer(4)
let array = new Uint8Array(buffer)
array[0] = 88
buffer:
原来:
00
现在:
58(十六进制)
因为:
Uint8Array
直接修改内存。
八、HTTP 下载返回 ArrayBuffer
HarmonyOS:
httpRequest.request(
{
url:url,
expectDataType:http.HttpDataType.ARRAY_BUFFER
}
)
返回:
ArrayBuffer
转换:
let uint8 = new Uint8Array(result.result as ArrayBuffer)
即可操作:
console.info(uint8[0])
九、文件读取返回 ArrayBuffer
例如:
let buffer = fs.readSync(fd)
得到:
ArrayBuffer
转换:
let bytes = new Uint8Array(buffer)
即可:
遍历文件
十、Uint8Array 转字符串
例如:
let array = new Uint8Array([
72,
101,
108,
108,
111
])
转换:
let decoder = new TextDecoder()
let str = decoder.decode(array)
console.info(str)
输出:
Hello
十一、字符串转 Uint8Array
let encoder = new TextEncoder()
let bytes = encoder.encode("HarmonyOS")
输出:
Uint8Array
十二、字符串 → ArrayBuffer
let encoder = new TextEncoder()
let uint8 = encoder.encode("HarmonyOS")
let buffer = uint8.buffer
完成:
String
↓
Uint8Array
↓
ArrayBuffer
十三、ArrayBuffer → 字符串
let decoder = new TextDecoder()
let uint8 = new Uint8Array(buffer)
let text = decoder.decode(uint8)
十四、复制 ArrayBuffer
注意:
let b2 = b1
不是复制。
只是引用:
b1
↓
内存
↑
b2
真正复制:
let copy = buffer.slice(0)
或者:
let src = new Uint8Array(buffer)
let dst = new Uint8Array(src)
let newBuffer = dst.buffer
十五、复制 Uint8Array
let src = new Uint8Array([1,2,3])
let dst = new Uint8Array(src)
输出:
1 2 3
此时:
不是共享内存。
十六、ArrayBuffer 与 Uint8Array 的区别
| 对比项 | ArrayBuffer | Uint8Array |
|---|---|---|
| 是否存储数据 | ✔ | ✖(视图) |
| 是否可读写 | ✖ | ✔ |
| 是否能遍历 | ✖ | ✔ |
| 是否支持下标 | ✖ | ✔ |
| 是否共享内存 | 本体 | 与 ArrayBuffer 共享 |
| 是否固定长度 | ✔ | 视图长度可指定 |
十七、实际开发场景
1. HTTP 下载
ArrayBuffer
↓
Uint8Array
↓
解析 JSON / 图片
2. MQTT
payload(ArrayBuffer)
↓
Uint8Array
↓
字符串
3. AES 加密
String
↓
Uint8Array
↓
ArrayBuffer
↓
AES
4. 图片上传
图片
↓
ArrayBuffer
↓
Uint8Array
↓
HTTP Body
5. BLE 通信
设备数据
↓
ArrayBuffer
↓
Uint8Array
↓
解析协议
十八、常见问题
Q1:什么时候使用 ArrayBuffer?
当 API 返回或要求原始二进制数据时,例如:
- 文件读取
- 网络下载
- Socket 通信
- 蓝牙数据
- 加密输入
Q2:什么时候使用 Uint8Array?
当需要读取、修改、遍历字节时,使用 Uint8Array。
Q3:ArrayBuffer 和 Uint8Array 转换会复制数据吗?
不会。
const buffer = new ArrayBuffer(4)
const view = new Uint8Array(buffer)
这里只是创建了一个新的视图,共享同一块内存,时间复杂度为 O(1),不会额外复制数据。
如果需要独立副本,需要主动复制,例如:
const copy = new Uint8Array(view)
或:
const newBuffer = buffer.slice(0)
Q4:可以有多个 Uint8Array 指向同一个 ArrayBuffer 吗?
可以。
const buffer = new ArrayBuffer(8)
const view1 = new Uint8Array(buffer)
const view2 = new Uint8Array(buffer)
view1[0] = 255
console.info(view2[0]) // 255
多个视图共享同一块底层内存,一个视图修改数据,其他视图立即可见。
十九、总结
在 HarmonyOS NEXT 中,ArrayBuffer 和 Uint8Array 是处理二进制数据最核心的一组类型,它们并不是互相替代,而是相互配合:
- ArrayBuffer:表示一块连续的原始内存,本身不能直接读写。
- Uint8Array:是
ArrayBuffer的字节视图,用于读取、修改和遍历数据。 - ArrayBuffer → Uint8Array:使用
new Uint8Array(buffer),不会复制数据。 - Uint8Array → ArrayBuffer:直接通过
uint8Array.buffer获取底层缓冲区,同样不会复制数据。 - 需要独立副本时,应使用
buffer.slice()或重新创建新的Uint8Array进行复制。
更多推荐




所有评论(0)