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. session设置过期的方法(转载)

    这篇文章主要介绍了php中实现精确设置session过期时间的方法,需要的朋友可以参考下   大多数据情况下我们对于session过期时间使用的是默认设置的时间,而对于一些有特殊要求的情况下我们可以设 ...

  2. SAXReader简单实例解析HTML

    转载自:http://blog.csdn.net/seayqrain/article/details/5024068# 使用SAXReader需要导入dom4j-full.jar包. dom4j是一个 ...

  3. Problem B: 大整数的加法运算

    Problem B: 大整数的加法运算 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 112  Solved: 57[Submit][Status][W ...

  4. vue 响应式原理

    Vue 采用声明式编程替代过去的类 Jquery 的命令式编程,并且能够侦测数据的变化,更新视图.这使得我们可以只关注数据本身,而不用手动处理数据到视图的渲染,避免了繁琐的 DOM 操作,提高了开发效 ...

  5. 【2】构建一个SSM项目结构

    初步思考一下这个项目的结构,由于是给一个比较老的公司做这个外包项目,服务器是搭建在windows操作系统上的Tomcat6.0,系统的JDK版本也是JDK1.6,都是比较旧. 数据库方面有专人负责,所 ...

  6. maven下的sqlserver配置jar包

    看了两天的maven,开始把之前做的ssm项目搭建成maven项目,结果在sqlserver的依赖包上受阻,sqlserver需要sqljdbc4.jar包,经过一系列百度教程才得以解决,现在总结一下 ...

  7. Office2016 KMS激活

    Office标准版激活 一新买本子需要安装Office,闲来无事就安装了一款Office Standard 2016,网上许多激活秘钥均已过期,无法激活,无奈下选择KMS激活. KMS下载链接如下: ...

  8. [拓扑排序]Ordering Tasks UVA - 10305

    拓扑排序模版题型: John has n tasks to do.Unfortunately, the tasks are not independent and the execution of o ...

  9. 十、Hadoop学习笔记————Hive与Hbase以及RDBMS(关系型数据库)的关系

    Hive目的是为了简化MapReduce编程 实际应用中,Hive与Hbase不经常链接

  10. 《Android源码设计模式》学习笔记之ImageLoader

    微信公众号:CodingAndroid cnblog:http://www.cnblogs.com/angel88/ CSDN:http://blog.csdn.net/xinpengfei521 需 ...