为你推荐一款高效的HarmonyOS鸿蒙Next IO组件——okio
为你推荐一款高效的HarmonyOS鸿蒙Next IO组件——okio 原文:https://mp.weixin.qq.com/s/XnNhSq8ESoslb2DQEzMbCQ,点击链接查看更多技术内容。
文章转载自“HarmonyOS开发者”微信公众号
前不久,三方组件库上新了一批JS/eTS组件,其中就包括okio组件。okio是一个可应用于HarmonyOS的高效IO库,它依托于系统能力,提供字符串的编解码转换能力,基础数据类型的读写能力以及对文件读写的支持。本期将为大家介绍okio的工作原理及使用方法。
一、okio的产生背景
为了满足开发者对IO的更高要求,三方组件库推出IO处理利器——okio(JS版本)。okio使用Segment作为数据存储容器,通过提供Segment移动、共享、合并和分割的能力,让数据读写变得非常灵活,也减少了数据复制,提升了IO效率。此外,okio还通过SegmentPool对Segment进行回收和复用,减少大量创建Segment带来的系统消耗。
二、两个基本概念
在深入解析okio的工作原理之前,我们先来了解两个基本概念:Segment和SegmentPool。
1. Segment
okio将数据分割成一块块的片段存放在Segment里面。Segment是一个数据存储的真正类,内部维护着一个大小为8192字节的字节数组用于存储数据。Segment最小可共享、可写入的数据大小为1024字节。Segment使用pos、limit、shared、owner、prev、next来分别记录读写位置、是否可写入、是否能共享、数据拥有者、前置节点和后置节点信息。Segment对外提供sharedCopy、unsharedCopy、split、push、pop、compact、writeTo等接口用于操作数据。
Segment同时拥有前置节点和后置节点,构成一个双向链表。读取数据的时候,从双向链表的头部开始读取;而写入数据的时候,从双向链表的尾部写入数据。
2. SegmentPool
为了管理Segment,okio维护了一个Segment对象池(即SegmentPool),对废弃的Segment回收、复用和内存共享,从而减少内存的申请和GC(garbage collection,垃圾收集)的频率,使性能得到优化。SegmentPool是一个由最多8个Segment组成的单链表。一个Segment的最大大小是8192字节(即8KB),所以SegmentPool的最大大小是64KB。
三、okio的工作原理
okio组件最重要的功能就是“读”和“写”。下面我们就从读写开始,了解okio的工作原理。
1. 读写数据
okio读写数据的过程中,遵循大块数据移动、小块数据复制的原则。okio从输入流读取数据到输入流缓冲区时,会先找到双向链表尾部的Segment节点,如果此节点的剩余容量足够,则直接将读取到的数据存入到此节点。如果此节点的剩余容量不足,则从SegmentPool里面取一个Segment链接到双向链表的尾部,然后将数据存入这个新节点。okio从输入流缓冲区读取数据,再写入数据到输出流缓冲区。这个过程比较复杂,有以下几种情况:
(1) 从输入流缓冲区获取到Segment,如果数据是满的(字节数组data长度为8092字节),那么直接修改此Segment的prev和next信息,将其添加到输出流缓冲区的双向链表的尾部,省去一次数据复制过程。
(2) 从输入流缓冲区获取到Segment(假设为Segment1),如果数据不是满的,可以通过pos和limit信息来确定segment1的可读数据,再和输出流缓冲区的双向链表的尾部节点(假设为Segment2)的剩余容量进行对比:
- 如果Segment1的可读数据比Segment2的剩余容量小,则把Segment1的数据复制到Segment2,然后回收Segment1到SegmentPool。
- 如果Segment1的可读数据比Segment2的剩余容量大,那么直接修改Segment1的prev和next信息,将其添加到Segment2的后面。
(3) 从输入流缓冲区获取到Segment(假设为Segment3),如果只需要传递部分数据(比如总数据为4096字节,只传递1024字节),okio会通过split接口将Segment3拆分成含3072字节数据的Segment3-1和含1024字节数据的Segment3-2,然后按照(2)的逻辑将Segment3-2的数据写入输出流缓冲区。
2. Segment的回收与复用
接下来,我们再来看看SegmentPool是如何回收和复用Segment的。
每次okio想要使用Segment就从SegmentPool中获取,使用完毕后又会放回到SegmentPool中等待复用,核心方法为take()和recycle()。
(1) take()方法
take()方法负责从对象池单链表的头部获取可以使用的Segment。如果获取不到,说明单链表是空的,此时新创建一个Segment给缓冲区使用。如果能获取到,则取出单链表的头部节点,再将下一个节点置为单链表的头部节点,并将取出来的Segment的next置空,同时更新对象池大小。
(2) recycle()方法
recycle()方法负责回收缓冲区里面使用完毕的Segment。回收开始时,首先更新对象池大小,然后把回收对象Segment添加到单链表头部,接着重置Segment的pos和limit为0。注意,以下情况不会回收Segment:
- 当前Segment的prev和next不为空
- 当前Segment是共享的
- 对象池已经有8个Segment了
3. 字符串处理
除了Segment和SegmentPool外,okio还封装了ByteString类来进行字符串处理。ByteString提供Base64编解码、utf-8编码、十六进制编解码、大小写转换、内容比较等丰富的API,可以很方便地处理字符串。在进行字符串处理时,由于ByteString同时持有原始字符串和对应的字节数组,可以直接使用字节数组里面的数据进行操作,不需要先将字符串转换为字节数组。特别是在频繁转换编码的场景下,通过这种以空间换时间的方式,可以避免字符串与字节数组的多次转换,减少了时间和系统性能消耗。
四、okio的使用及示例
1. 前置配置
步骤一:在entry的package.json文件中添加以下依赖项。
"dependencies": {
"okio": "^1.0.0"
}
步骤二:配置仓库镜像地址。
npm config set @ohos:registry=https://repo.harmonyos.com/npm/
步骤三:DevEco Studio的Terminal里面输入以下命令下载源代码。
cd entry
npm install @ohos/okio
步骤四:文件的头部引入okio库。
import okio from '@ohos/okio';
步骤五:在config.json文件中申请存储权限。
"reqPermissions": [
{
"name": "ohos.permission.WRITE_USER_STORAGE",
"reason": "Storage",
"usedScene": {
"when": "always",
"ability": [
"com.example.okioapplication.MainAbility"
]
}
},
{
"name": "ohos.permission.READ_USER_STORAGE",
"reason": "Storage",
"usedScene": {
"when": "always",
"ability": [
"com.example.okioapplication.MainAbility"
]
}
},
{
"name": "ohos.permission.WRITE_EXTERNAL_MEDIA_MEMORY",
"reason": "Storage",
"usedScene": {
"when": "always",
"ability": [
"com.example.okioapplication.MainAbility"
]
}
}
]
2. 代码实现
执行完上面的配置操作后,就可以进入代码编写阶段了。开发者可以使用okio提供的丰富的API接口来实现功能。下面为大家展示四个实现示例,供大家参考学习。
示例1:文件写入和读取
本示例通过sink将内容写入文件,通过source从文件读取内容。代码如下:
//通过sink将内容写入文件
var sink = new okio.Sink(this.fileUri);
sink.write(this.Value, false);
//通过source从文件读取内容
var source = new okio.Source(this.fileUri);
source.read().then(function (data) {
context.readValue = data;
}).catch(function (error) {
console.log("error=>" + error);
});
示例2:Base64解码
本示例通过ByteString实现Base64解码功能,代码如下:
let byteStringObj = new okio.ByteString('');
let decodeBase64 = byteStringObj.decodeBase64('SGVsbG8gd29ybGQ=');
this.decodeBase64Value = JSON.stringify(decodeBase64);
示例3:十六进制解码
本示例通过ByteString实现十六进制解码功能,代码如下:
let byteStringObj = new okio.ByteString('');
let decodehex = byteStringObj.decodeHex('48656C6C6F20776F726C640D0A');
this.decodeHexValue = JSON.stringify(decodehex);
示例4:Utf8编码
本示例通过ByteString实现Utf8编码功能,代码如下:
let byteStringObj = new okio.ByteString('');
let encodeUtf8 = byteStringObj.encodeUtf8('Hello world #4 ❤ ( ͡ㆆ ͜ʖ ͡ㆆ)');
this.encodeUtf8Value = JSON.stringify(encodeUtf8);
本期okio组件就为大家介绍到这里了。okio组件已开源,欢迎大家参与贡献。
开源地址: https://gitee.com/openharmony-tpc/okio
还想了解更多优秀的组件? 欢迎点击三方组件库链接 https://gitee.com/openharmony-tpc/tpc_resource
更多优秀组件等你来发现!
更多关于为你推荐一款高效的HarmonyOS鸿蒙Next IO组件——okio的实战教程也可以访问 https://www.itying.com/category-93-b0.html
学习了
学习了
HarmonyOS鸿蒙Next中的okio是一个高效的IO组件,专为处理数据流而设计。它提供了简洁的API,支持同步和异步操作,适用于文件读写、网络通信等场景。okio通过减少内存复制和优化缓冲区管理,提升了IO性能。它还与鸿蒙系统的其他组件无缝集成,确保了系统的稳定性和兼容性。okio的设计理念是简化开发者的工作,使他们能够更专注于业务逻辑,而不是底层IO处理。在鸿蒙生态中,okio是开发高效应用的得力工具。
在HarmonyOS鸿蒙Next中,推荐使用okio
作为高效的IO组件。okio
是Square公司开发的一个轻量级IO库,专为高效处理字节流和字符流设计。它提供了简洁的API,支持缓冲、分块读取、超时控制等功能,特别适合处理大文件或网络流数据。在鸿蒙系统中,okio
可以与原生API无缝集成,提升IO操作的性能和开发效率。通过okio
,开发者可以更轻松地实现高效、可靠的IO处理,适用于文件操作、网络通信等多种场景。