1.简介
Okio是由square公司开发的,它补充了java.io和java.nio的不足,以便能够更加方便,快速的访问、存储和处理你的数据。
2.ByteStrings and Buffers
Okio是围绕两种类型构建的,它们将很多功能都包含在一个简单的API中:
ByteString是一个不可变的字节序列。对于字节数据来说,String是最近基本的。ByteString是String的一个孪生兄弟,使得它能更简单的去处理二进制数值。这个类提供了相应的API去进行16进制、base64和UTF-8的编码和解码。
Buffer 是一个可变的字节序列,[正如ArrayList一样是可变的]。你不需要提前去设置缓冲区的大小。你可以将缓冲区当做一个队列来进行读取:即从头部读数据,从尾部写入数据。读写的位置,队列大小的限制,或者队列的容量都是不需要去考虑的。
ByteStrng
和Buffer
在内部做了许多优化来节省CPU和内存的开销。如果您将一个UTF-8字符串编码为ByteString,它会缓存对该字符串的引用,以便稍后对其进行解码时,无需执行任何操作。
Buffer
是一个由Segment构成的链表结构的实现。当你从一个Buffer移动数据到另一个Buffer时,内部的操作是为其所以Segments重新分配内存,而不仅仅是复制数据。这个方法对于多线程编程来说是特别有帮助的:即一个访问网络的线程不需要复制就可以与一个工作线程进行数据交互。
3.Sources and Sinks
java.io
设计的一个优雅部分是如何将流为了正如加密和压缩等转换操作而分层。Okio包括自己的流类型,称为 Source 和 Sink ,像InputStream和OutputStream一样工作,但有一些关键的区别:
-
Timeouts
流提供了对底层I/O机制的访问。与java.io
套接字(Socket)流不同,它的read()
和write()
方法都支持超时。 -
Easy to implement
Source
生命了三个方法:
read()
,
close()
timeout()
没有像available()
这样有可能导致读取单字节不正确和损耗性能的操作。 -
Easy to use
虽然要实现Source和Sink接口只有三个方法可以重写,但调用者可以通过BufferedSource和BufferedSink接口获得丰富的API。 这些接口能在你需要的地方给你所需要的一切。 -
No artificial distinction between byte streams and char streams.
所有的数据都是被当做字节数组、UTF-8字符串、大端的32位整型数据、小端的short类型来进行读写的。 -
Easy to test.
Buffer
类实现了BufferedSource
和BufferedSink
接口。所以你的测试代码可以变得很整洁简单。
Sources and Sinks是和InputStream
以及OutputStream
进行交互操作的.你能够将Source
看做一个InputStream
,同样的,将一个InputStream
看作是一个Source
。同样的,你也可以将一个Sink
看做一个OutputStream
.
Okio最初是作为OkHttp的一个组件,即Android中包含的HTTP + SPDY客户端。 它运转良好,并准备好解决新的问题。
4.Example: A PNG decoder
在PNG解码实战中应用Okio:
private static final ByteString PNG_HEADER = ByteString.decodeHex("89504e470d0a1a0a");
public void decodePng(InputStream in) throws IOException {
BufferedSource pngSource = Okio.buffer(Okio.source(in));
ByteString header = pngSource.readByteString(PNG_HEADER.size());
if (!header.equals(PNG_HEADER)) {
throw new IOException("Not a PNG.");
}
while (true) {
Buffer chunk = new Buffer();
// Each chunk is a length, type, data, and CRC offset.
int length = pngSource.readInt();
String type = pngSource.readUtf8(4);
pngSource.readFully(chunk, length);
int crc = pngSource.readInt();
decodeChunk(type, chunk);
if (type.equals("IEND")) break;
}
pngSource.close();
}
private void decodeChunk(String type, Buffer chunk) {
if (type.equals("IHDR")) {
int width = chunk.readInt();
int height = chunk.readInt();
System.out.printf("%08x: %s %d x %d%n", chunk.size(), type, width, height);
} else {
System.out.printf("%08x: %s%n", chunk.size(), type);
}
}
网友评论