Okio 是一个包装了 java.iojava.nio api 的库,以便可以更容易的访问、存储以及处理数据。

ByteStrings 和 Buffers

Okio 是围绕着两个容器类构建起来的:

  • ByteString 是一个不可变的字节序列。对于字符数据,Java 中的 String 类提供了基本的支持。ByteString 就像是 String 失散多年的兄弟,对二进制数据提供了基本的支持。这个类是非常人性化的:它明白如何编码或解码自身来作为十六进制字符串、base64 字符串或者 UTF-8 字符串。
  • Buffer 是一个可变的字节序列。就像 ArrayList 一样,你不需要提前规定你的 buffer 的大小。你可以像读写队列一样读写 buffer:写数据到末尾、从头部读数据。你不需要负责管理 positions, limits, 以及 capacities

ByteStringBuffer 内部做了一些优化以便节省 CPU 和内存资源。如果你把一个 UTF-8 的字符串转换为 ByteStringByteString 会缓存这个字符串的引用,之后如果你在解码时就直接返回这个字符串引用即可,无需做什么额外的工作。

Buffer 是由段(segment)链表组成的。当你从一个 Buffer 移动数据到另外一个 Buffer 时,它只是重新设置了段(segment)的拥有者而不是复制数据。这种方法对于多线程程序将是非常有用的:网络线程可以和工作者线程交换数据而无需任何的复制。

Sources 和 Sinks

java.io 原生 API 设计精妙的一处就是流数据可以分层进行转换处理,比如:加密和压缩。就像 InputStreamOutputStream,Okio 也包含了自己的流类型 SourceSink ,但是却有几点关键性的不同之处:

  • 超时机制。Okio 的流类型对底层 I/O 访问时增加了超时机制,而 java.io 套接字流的 read()write() 方法均是永不超时的。
  • 实现简单。Source 类声明了三个方法:read(), close(), 和 timeout(),不存在像 available() 这种危险的方法或者单字节读取数据这种容易造成性能问题的方法。
  • 容易使用。尽管 SourceSink 只有三个方法来读写数据,但是调用者可以使用功能丰富的实现类 BufferedSourceBufferedSink 接口。
  • 对于字节流和字符流没有人工区别。Okio 中字节流和字符流都是一样的,可以以字节流,UTF-8 字符串,大端 32位整数,小端短整数来读写。不再有 InputStreamReader
  • 容易测试。Buffer 类实现了 BufferedSourceBufferedSink 接口,所以你的测试代码将是简单清晰的。

Sources 加 sinks 和 InputStreamOutputStream 内部是可以互相操作的。所以你可以把 Source 看做一个 InputStream,并且也可以把 InputStream 看做一个 SourceSinkOutputStream 同样如此。

示例:一个 PNG 解码器

package okio;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; /**
* Created by clearbug on 2017/11/5.
*/
public class PngDecoder {
private static final ByteString PNG_HEADER = ByteString.decodeHex("89504e470d0a1a0a"); public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("/Users/clearbug/Pictures/Small-mario.png");
PngDecoder pngDecoder = new PngDecoder();
pngDecoder.decodePng(inputStream);
} public void decodePng(InputStream in) throws IOException {
try (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;
}
}
} 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);
}
}
}

Okio 之初探黄龙的更多相关文章

  1. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  2. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...

  3. 从273二手车的M站点初探js模块化编程

    前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...

  4. JavaScript学习(一) —— 环境搭建与JavaScript初探

    1.开发环境搭建 本系列教程的开发工具,我们采用HBuilder. 可以去网上下载最新的版本,然后解压一下就能直接用了.学习JavaScript,环境搭建是非常简单的,或者说,只要你有一个浏览器,一个 ...

  5. .NET文件并发与RabbitMQ(初探RabbitMQ)

    本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址:http://www.cnblogs.com/tdws/p/5860668.html 想必MQ这两个字母对于各位前辈们和老司 ...

  6. React Native初探

    前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...

  7. 【手把手教你全文检索】Apache Lucene初探

    PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程,仅供各位程序猿们参考,这其中不涉及任何私密话题,因此也 ...

  8. Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

    一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...

  9. NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

    一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器 ...

随机推荐

  1. Apache和Tomcat整合(一个Apache 不同域名处理多个不同业务)

    一.简介 在项目中,几乎任何一个项目都包括静态资源和动态请求两大部分.特别对于门户网站这样的项目,静态内容资源会更多,我们使用一般的 Tomcat 部署时,Tomcat 对静态资源的处理能力比较慢,至 ...

  2. 使用ichartjs生成图表

    官网:http://www.ichartjs.com/ ichartjs 是一款基于HTML5的图形库.使用纯javascript语言, 利用HTML5的canvas标签绘制各式图形. ichartj ...

  3. heapster源码分析——kubelet的api调用分析

    一.heapster简介 什么是Heapster? Heapster是容器集群监控和性能分析工具,天然的支持Kubernetes和CoreOS.Kubernetes有个出名的监控agent---cAd ...

  4. RobotFramework自动化测试环境配置

    现在工作是做自动化测试平台维护的,平台用的C#做的,主要是用来测试CMBRun项目,它是c/s结构的项目,而b/s结构的项目主要使用RF+Python来做.做这块之前听过自动化测试,身边的朋友也有做这 ...

  5. selenium元素定位

    在网页自动化测试中,我们要让程序自动模拟我们的点击.输入.悬浮.拖动等操作,完成我们的测试用例组. 输入.点击.打开这样的动词,已经包含在了selenium的方法中,可以直接调用(当然你也可以自己写) ...

  6. distcc (dcc_execvp) ERROR: failed to exec XX: Permission denied

    首先先确保一下是不是能执行下面语句: # sudo -u nobody XX --version 如果能看见版本信息,则可以不用往下看. 再检查一下distccd.service # sudo cat ...

  7. linq中group by

    本文导读:LINQ定义了大约40个查询操作符,如select.from.in.where.group 以及order by,借助于LINQ技术,我们可以使用一种类似SQL的语法来查询任何形式的数据.L ...

  8. C#截取当前活动窗体的图片

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. 设计模式的征途—23.解释器(Interpreter)模式

    虽然目前计算机编程语言有好几百种,但有时人们还是希望用一些简单的语言来实现特定的操作,只需要向计算机输入一个句子或文件,就能按照预定的文法规则来对句子或文件进行解释.例如,我们想要只输入一个加法/减法 ...

  10. Json字符串解析原理、超大json对象的解析

    概述 附上完整的代码:https://pan.baidu.com/s/1dEDmGz3(入口类是Json)JSON:JavaScript 对象表示法(JavaScript Object Notatio ...