一、输入输出
在正式介绍 Okio 之前,让我们先回忆一下输入/输出流
的概念。
-
输入流:外设——>内存
将数据从各种外设(如键盘、文件、网络、数据库等)读取到内存中;
-
输出流:内存——>外设
与输入流相反,是将内存数据写入到各种外设(如文件、网络、数据库、显示器等);
二、Okio简介
Okio最初是作为OkHttp的一个组件
出现,是 OkHttp 实现HTTP协议数据构建、解析中使用到的底层 IO 库。其相比于传统的 java.io 和 java.nio ,其在文件
、网络
等数据读写操作更加便捷、高效
。
Okio
的设计思想是将数据的读写
操作封装为一个统一的接口,即 Source
和 Sink
,其中 输入为Source,输出为Sink 。
-
Okio
还提供了Buffer
和ByteString
用于封装和操作字节数据
,提高数据读写的效率。 - 同时,
Okio
还提供了一些工具方法,例如从InputStream
或OutputStream
中创建BufferedSource
、BufferedSink
等。
三、引入Okio
Okio官方API地址为:Okio (square.github.io)
Okio Github开源地址为: GitHub - square/okio: A modern I/O library for Android, Java, and Kotlin Multiplatform.
使用 Okio 时,我们可以查阅官方最新版本,并通过如下方式引入Okio:
implementation("com.squareup.okio:okio:3.2.0")
四、API 简介及使用
- Buffer 简介及API使用介绍
- ByteString 简介及API使用介绍
- Source 和 Sink 使用介绍
4.1 Buffer
Buffer
是一个大小可变的字节缓冲区
,在Okio中Buffer
是BufferedSource
和BufferedSink
的接口实现类,用户实现字节数据的缓冲与读写。
官方API描述如下:
-
Buffer
可以像Arraylist
一样,不需要预先设置缓冲区的大小,而是随着数据的增加自动扩充缓冲区大小
。 -
Buffer
由很多的Segment
片段构成,每个Segment
中维护一个字节数组
。 -
Buffer
中以链表的形式来管理Segment
,当使用Buffer
进行缓冲区字节数据移动时,其只改变Segment
字节数组的所有权,从而提高字节数组的移动效率。
okio.Buffer
字节缓冲区的使用方式举例如下:
import okio.Buffer; Buffer buffer = new Buffer(); // 向缓冲区写入数据 buffer.writeUtf8("key"); buffer.writeByte('='); buffer.writeUtf8("value"); // 缓冲区字节大小 int byteCount = buffer.size(); // 读取换区中的全部字节数据 byte[] byteArray = buffer.readByteArray(); // 以Utf8编码的形式输出所有字符串 String result = buffer.readUtf8(); // 清空缓冲区 buffer.clear();
4.2 ByteString
ByteString
中维护了大小不可变的字节数组
,其可以对存入该字节数组的数据进行base64
、utf8
、md5
、sha256
等字符串的编解码操作。 ByteString
更像是一个工具类,在Okio
中其重要应用场景也是在网络传输中对数据进行编码和解码工作
。
官方API描述如下:
其部分静态方法和公有方法如下图所示:
okio.ByteString
的使用方式举例如下:
import okio.ByteString; // utf8编码 ByteString byteString = ByteString.encodeUtf8("hello"); // HEX ByteString byteString = ByteString.decodeHex("hello"); // 输出utf8字符串 String result = byteString.utf8();
4.3 Source 和 Sink
Source 和 Sink 在前文中提到过输入为Source,输出为Sink。在 Okio 中,Source
和 Sink
用于读取
和写入
数据的抽象类
,其提供了一组标准的IO读写方法,可以方便地进行数据的读写操作。
// Okio源码:输入流 Source // Source 接口类,最主要的方法是 read public interface Source extends Closeable { // 读字节数据 long read(Buffer var1, long var2) throws IOException; // timeout Timeout timeout(); void close() throws IOException; } // Okio源码:输出流 Sink // Sink 接口类,最主要的方法是 write public interface Sink extends Closeable, Flushable { // 写字节数据 void write(Buffer var1, long var2) throws IOException; void flush() throws IOException; Timeout timeout(); void close() throws IOException; }
在把前文已经展示过的Okio结构图拿出来:
-
Source
的最终实现类是RealBufferedSource
; -
Sink
的最终实现类是RealBufferedSink
;
使用 okio.Source
从文件中读取数据,代码举例如下:
// 使用 Source 从文件中读取数据 public static void readLines(File file) throws IOException { // 输入流 Source fileSource = Okio.source(file); // 构建 BufferedSource RealBufferedSource bufferedSource = Okio.buffer(fileSource); // 循环读取 while (true) { // 读取行数据 String line = bufferedSource.readUtf8Line(); if (line == null) { break; } } }
使用 okio.Sink
向文件中写入数据,代码举例如下:
// 使用 Sink 向文件中写入数据 public static void writeToFile(File file) throws IOException { // 创建输出流 Sink fileSink = Okio.sink(file); // 构造 BufferedSink RealBufferedSink bufferedSink = Okio.buffer(fileSink); // 向文件中写入数据 bufferedSink.writeUtf8("Hello"); bufferedSink.writeUtf8("\n"); bufferedSink.writeAll(Okio.source(new File("my.txt"))); }
以上就是一文详解Android中Okio输入输出流的详细内容,更多关于Android Okio输入输出流的资料请关注寻技术其它相关文章!