在 OkHttp 的源码中,我们常常能看到 Okio
的身影,这篇文章,我们把Okio
拿出来进行一个详细的介绍学习。
- 输入输出的概念简述
- Okio 简介
- 工程中引进 Okio
- API 简介及运用介绍
一、输入输出
在正式介绍 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地址为: square.github.io/okio/
Okio Github开源地址为: github.com/square/okio
运用 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")));
}
五、参阅
Okio API: square.github.io/okio/
Okio Github: github.com/square/okio
Java流: c.biancheng.net/view/1119.h…
= THE END =
文章首发于大众号”CODING技术小馆“,假如文章对您有协助,欢迎关注我的大众号。