HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?

HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?

  1. TaskPool中在子线程获取到数据,是用 collectios.ArrayBuffer 包装传递的。

  2. 传递过来后,需要将buffer写入文件。

  3. @ohos.file 只认标准ArrayBuffer进行文件读写,不支持 collectios.ArrayBuffer。

要完成此目的,我需要

  1. 拷贝 collectios.ArrayBuffer 的内容到 ArrayBuffer,然后写入文件。

但是如果需要拷贝内容的话,那使用 collectios.ArrayBuffer 做跨线程传输数据的意义何在? 还有其他的处理方式吗?


更多关于HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

Transferable对象(NativeBinding对象)

通过该对象,直接进行数据的传输,传输类型就是主线程能够接受的类型ArrayBuffer,更加直接有效,效率还高。

Transferable对象有共享模式和转移模式,建议采用转移模式,完整案例参考官方文档:Transferable对象(NativeBinding对象)-线程间通信对象-并发线程间通信-ArkTS并发-ArkTS(方舟编程语言)-应用框架 - 华为HarmonyOS开发者

更多关于HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


@ohos.file.fs模块仅支持标准ArrayBuffer,而collectios.ArrayBuffer需转换才能使用。TaskPool默认采用转移模式传递ArrayBuffer,原线程无法继续操作数据,但拷贝传输可保留数据。

零拷贝办法:通过C++层直接操作底层内存,避免ArkTS层拷贝

Native侧代码:

// C++层通过napi接口共享内存
napi_value GetNativeBuffer(napi_env env, napi_callback_info info) {
  void* nativeBuffer = // 获取collectios.ArrayBuffer底层指针;
  size_t bufferSize = // 获取缓冲区大小;

  napi_value arrayBuffer;
  napi_create_arraybuffer(env, bufferSize, &nativeBuffer, &arrayBuffer);
  return arrayBuffer;
}

ArkTS侧调用:

// 获取转换后的标准ArrayBuffer
const nativeBuffer = nativeModule.getNativeBuffer() as ArrayBuffer;
fs.writeSync(filePath, nativeBuffer.buffer);

在HarmonyOS Next中,若需直接处理ArrayBuffer与文件I/O的交互,可使用fs.openSync()获取文件描述符后,通过fs.readSync()/fs.writeSync()指定ArrayBuffer作为缓冲区参数。对于大文件,采用FileReaderreadAsArrayBuffer()方法可直接读取为ArrayBuffer,或通过Blob.arrayBuffer()转换。流式处理可使用ReadableStream/WritableStreampipeTo()方法避免完整拷贝。

在HarmonyOS Next中处理collections.ArrayBuffer与标准ArrayBuffer的转换问题,确实存在性能考量。以下是几种可行的解决方案:

  1. 直接转换方案(推荐): 使用collections.ArrayBuffer的toArrayBuffer()方法进行零拷贝转换:
const collectionsBuffer = ...; // 从TaskPool获取的buffer
const standardBuffer = collectionsBuffer.toArrayBuffer();
// 现在可以直接用@ohos.file API写入standardBuffer
  1. 流式处理方案: 如果数据量很大,可以采用流式处理避免内存峰值:
const chunkSize = 8192;
const writer = await fs.createStreamWriter(filePath);
for (let i = 0; i < collectionsBuffer.byteLength; i += chunkSize) {
    const chunk = collectionsBuffer.slice(i, i + chunkSize).toArrayBuffer();
    await writer.write(chunk);
}
await writer.close();
  1. 底层API方案: 对于性能敏感场景,可以使用更底层的NativeBuffer API进行直接内存操作:
import nativeBuffer from '@ohos.nativeBuffer';
const nativeBuf = nativeBuffer.wrap(collectionsBuffer);
const stdBuffer = nativeBuf.getArrayBuffer();

这些方案都能避免完整的数据拷贝,其中第一种方案在大多数场景下是最简洁高效的。

回到顶部