前言

在 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 中,ArrayBufferUint8Array 是处理二进制数据最核心的一组类型,它们并不是互相替代,而是相互配合:

  • ArrayBuffer:表示一块连续的原始内存,本身不能直接读写。
  • Uint8Array:是 ArrayBuffer 的字节视图,用于读取、修改和遍历数据。
  • ArrayBuffer → Uint8Array:使用 new Uint8Array(buffer),不会复制数据。
  • Uint8Array → ArrayBuffer:直接通过 uint8Array.buffer 获取底层缓冲区,同样不会复制数据。
  • 需要独立副本时,应使用 buffer.slice() 或重新创建新的 Uint8Array 进行复制。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐