一、okio的產生背景
IO,即輸入輸出(Input/Output)。絕大多數應用都需要與外部進行數據交互,這就會涉及IO。系統提供了IO能力,在使用系統IO時,通常需要一個中間緩沖區來保存讀取到的數據。數據先從輸入流緩沖區復制到中間緩沖區,再從中間緩沖區復制到輸出流緩沖區。中間多次拷貝,降低了IO效率,同時增加了系統消耗。為了滿足開發者對IO的更高要求,三方組件庫推出IO處理利器——okio(JS版本)。okio使用Segment作為數據存儲容器,通過提供Segment移動、共享、合并和分割的能力,讓數據讀寫變得非常靈活,也減少了數據復制,提升了IO效率。此外,okio還通過SegmentPool對Segment進行回收和復用,減少大量創建Segment帶來的系統消耗。下面就帶大家深入了解JS版本的okio的工作原理,探索它是如何提升IO效率的~二、兩個基本概念
在深入解析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信息,將其添加到輸出流緩沖區的雙向鏈表的尾部,省去一次數據復制過程。

(3) 從輸入流緩沖區獲取到Segment(假設為Segment3),如果只需要傳遞部分數據(比如總數據為4096字節,只傳遞1024字節),okio會通過split接口將Segment3拆分成含3072字節數據的Segment3-1和含1024字節數據的Segment3-2,然后按照(2)的邏輯將Segment3-2的數據寫入輸出流緩沖區。

圖2 Segment拆分
拆分Segment的時候,可以通過參數指定拆分后的第一個Segment含有的未讀字節數(byteCount)。拆分后,第一個Segment包含的數據范圍是[pos,pos+byteCount),第二個Segment包含的數據范圍是[pos+byteCount,limit)。拆分Segment時也遵循大塊數據移動、小塊數據復制的原則。當byteCount大于1024時,使用共享的Segment,否則復制數據。(注:文件、流、socket相關的IO優化需要系統支持,待后續版本優化提供。)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了
四、okio的使用及示例
1. 前置配置步驟一:在entry 的package.json文件中添加以下依賴項。步驟二:配置倉庫鏡像地址。"dependencies": {"okio": "^1.0.0"}
npm config set @ohos:registry=https://repo.harmonyos.com/npm/
步驟三:DevEco Studio的Terminal里面輸入以下命令下載源代碼。步驟四:文件的頭部引入okio庫。cd entrynpm install @ohos/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將內容寫入文件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解碼

示例3:十六進制解碼let byteStringObj = new okio.ByteString.ByteString(''); //生成ByteString對象let decodeBase64 = byteStringObj.decodeBase64('SGVsbG8gd29ybGQ='); //解碼Base64字符串this.decodeBase64Value = JSON.stringify(decodeBase64); //顯示解碼結果

示例4:Utf8編碼let byteStringObj = new okio.ByteString.ByteString('');let decodehex = byteStringObj.decodeHex('48656C6C6F20776F726C640D0A');this.decodeHexValue = JSON.stringify(decodehex);

let byteStringObj = new okio.ByteString.ByteString('');let encodeUtf8 = byteStringObj.encodeUtf8('Hello world #4 ( ????? ??)');this.encodeUtf8Value = JSON.stringify(encodeUtf8);
本期okio組件就為大家介紹到這里了。okio組件已開源,歡迎大家參與貢獻。
開源地址如下:
https://gitee.com/openharmony-tpc/okio還想了解更多優秀的組件?歡迎點擊下方的“閱讀原文”,跳轉到三方組件庫,更多優秀組件等你來發現!審核編輯 :李倩
-
組件
+關注
關注
1文章
573瀏覽量
19023 -
HarmonyOS
+關注
關注
80文章
2153瀏覽量
36058
原文標題:為你推薦一款高效的IO組件——okio
文章出處:【微信號:HarmonyOS_Dev,微信公眾號:HarmonyOS開發者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
菲諾克科技推出沁恒CH9347有線透傳芯片應用于移動電源新國標方案
恒訊科技解析:如何安裝MySQL并創建數據庫
釘釘正式開源HarmonyOS圖片編輯組件
Aisler 發布 Lovely Library:一個為 KiCad 打造的高質量歐洲元器件庫
一個模塊通吃DI/DO/AI/AO!無線IO的萬能信號采集方案
一文詳解Advanced IO wizard異步模式
HarmonyOS入門指南
HarmonyOS實戰:3秒實現一個自定義輪播圖
HarmonyOS5云服務技術分享--云數據庫使用指南
一體式 IO 模塊:線纜設備車間高效控制的新引擎
Profinet 協議遠程 IO 模塊:端子機高效運行的關鍵助手
一個可應用于HarmonyOS的高效IO庫
評論