HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?
HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?
-
TaskPool中在子线程获取到数据,是用 collectios.ArrayBuffer 包装传递的。
-
传递过来后,需要将buffer写入文件。
-
@ohos.file 只认标准ArrayBuffer进行文件读写,不支持 collectios.ArrayBuffer。
要完成此目的,我需要
- 拷贝 collectios.ArrayBuffer 的内容到 ArrayBuffer,然后写入文件。
但是如果需要拷贝内容的话,那使用 collectios.ArrayBuffer 做跨线程传输数据的意义何在? 还有其他的处理方式吗?
更多关于HarmonyOS鸿蒙Next中collectios.ArrayBuffer与文件 I/O 不兼容,不想拷贝还能怎么处理?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
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
作为缓冲区参数。对于大文件,采用FileReader
的readAsArrayBuffer()
方法可直接读取为ArrayBuffer,或通过Blob.arrayBuffer()
转换。流式处理可使用ReadableStream
/WritableStream
的pipeTo()
方法避免完整拷贝。
在HarmonyOS Next中处理collections.ArrayBuffer与标准ArrayBuffer的转换问题,确实存在性能考量。以下是几种可行的解决方案:
- 直接转换方案(推荐): 使用collections.ArrayBuffer的toArrayBuffer()方法进行零拷贝转换:
const collectionsBuffer = ...; // 从TaskPool获取的buffer
const standardBuffer = collectionsBuffer.toArrayBuffer();
// 现在可以直接用@ohos.file API写入standardBuffer
- 流式处理方案: 如果数据量很大,可以采用流式处理避免内存峰值:
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();
- 底层API方案: 对于性能敏感场景,可以使用更底层的NativeBuffer API进行直接内存操作:
import nativeBuffer from '@ohos.nativeBuffer';
const nativeBuf = nativeBuffer.wrap(collectionsBuffer);
const stdBuffer = nativeBuf.getArrayBuffer();
这些方案都能避免完整的数据拷贝,其中第一种方案在大多数场景下是最简洁高效的。