Okio简化处理IO操作
来源:互联网 发布:电脑端怎么看手机淘宝 编辑:程序博客网 时间:2024/05/18 02:08
Okio底层通过两种包含多种能力的类提供丰富的API。它们是ByteStrings 和 Buffers。
ByteStrings
这个类提供了丰富的编码和解码操作,比如hex, base64, and UTF-8。
Buffers
它提供了字节缓冲区操作,类似队列结果,从头部读取数据,写入的数据添加到尾部。
由于内部高效的算法,ByteStrings和Buffer很大程度上节约了CPU资源和内存。
Okio有自己的流类型,叫做Source和Sink。Source类似java io中的InputStream,Sink类似java io中的OutputStream,但是又有一些关键的不同点:
1、Timeouts
读写提供了超时检查
2、接口实现很简单
Source只定义了三个方法:read(),close(),timeout().
3、使用更加简单
BufferedSource和BufferedSink基本上提供了你需要的任何功能
Okio中有两个关键的接口,Sink和Source,这两个接口都继承了Closeable接口;而Sink可以简单的看做OutputStream,Source可以简单的看做InputStream。而这两个接口都是支持读写超时设置的。结构图如下
它们各自有一个支持缓冲区的子类接口,BufferedSink和BufferedSource,而BufferedSink有一个实现类RealBufferedSink,BufferedSource有一个实现类RealBufferedSource;此外,Sink和Source它门还各自有一个支持gzip压缩的实现类GzipSink和GzipSource;一个具有委托功能的抽象类ForwardingSink和ForwardingSource;还有一个实现类便是InflaterSource和DeflaterSink,这两个类主要用于压缩,为GzipSink和GzipSource服务;整体的结构图如下
BufferedSink中定义了一系列写入缓存区的方法,比如write方法写byte数组,writeUtf8写字符串,还有一些列的writeByte,writeString,writeShort,writeInt,writeLong,writeDecimalLong等等方法;
BufferedSource定义的方法和BufferedSink极为相似,只不过一个是写一个是读,基本上都是一一对应的,如readUtf8,readByte,readString,readShort,readInt等等等等。这两个接口中的方法有兴趣的点源码进去看就可以了。
而这两个支持缓冲区的接口的实现类RealBufferedSink和RealBufferedSource都是通过包装一个Sink+Buffer或者Source+Buffer来进行实现的。如下图所示
拿RealBufferedSink来举例,实际调用的write的一系列方法,都是直接的对成员变量buffer进行的操作,当写入buffer成功后,最后会调用一个方法将buffer中的内容写入到sink中去,我们随便拿一个方法看一下
@Override public BufferedSink writeShort(int s) throws IOException {if (closed) throw new IllegalStateException("closed");buffer.writeShort(s);return emitCompleteSegments();}可以看到,首先会判断closed成员变量是否是标记着关闭,如果已经关闭了则扔出一个异常,否则将内容写入到buffer,写入完成后调用了一个emitCompleteSegments的方法,该方法中做了什么呢
@Override public BufferedSink emitCompleteSegments() throws IOException {if (closed) throw new IllegalStateException("closed");long byteCount = buffer.completeSegmentByteCount();if (byteCount > 0) sink.write(buffer, byteCount);return this;}
这两个实现类的内部的所有方法都是类似的,这里不一一展开。
而这一切的背后都是一个叫做Buffer的类在支持着缓冲区,Buffer是BufferedSink和BufferedSource的实现类,因此它既可以用来读数据,也可以用来写数据,其内部使用了一个Segment和SegmentPool,维持着一个链表,其循环利用的机制和Android中Message的利用机制是一模一样的。
/** * A collection of unused segments, necessary to avoid GC churn and zero-fill. * This pool is a thread-safe static singleton. */final class SegmentPool { /** The maximum number of bytes to pool. */ // TODO: Is 64 KiB a good maximum size? Do we ever have that many idle segments? static final long MAX_SIZE = 64 * 1024; // 64 KiB. /** Singly-linked list of segments. */ static Segment next; /** Total bytes in this pool. */ static long byteCount; private SegmentPool() { } static Segment take() { synchronized (SegmentPool.class) { if (next != null) { Segment result = next; next = result.next; result.next = null; byteCount -= Segment.SIZE; return result; } } return new Segment(); // Pool is empty. Don't zero-fill while holding a lock. } static void recycle(Segment segment) { if (segment.next != null || segment.prev != null) throw new IllegalArgumentException(); if (segment.shared) return; // This segment cannot be recycled. synchronized (SegmentPool.class) { if (byteCount + Segment.SIZE > MAX_SIZE) return; // Pool is full. byteCount += Segment.SIZE; segment.next = next; segment.pos = segment.limit = 0; next = segment; } }}内部一个成员变量next指向链表下一个元素,take方法首先判断池中是否存在可用的,存在则返回,不存在则new一个,而recycle则是将不再使用的Segment重新扔到池中去。从而达到一个Segment池的作用。
而Okio暴露给外部使用的类便是Okio这个类,其内部有大量的静态方法,包括通过一个Source获得BufferedSource,通过一个Sink获得一个BufferedSink。这个过程很简单,我们调用Okio的buffer方法即可返回我们需要的,如下
Okio.buffer(source);Okio.buffer(sink);但是上面两个方法需要传递一个Sink或者Source,那么这个Sink和Source又是如何获得的呢。其实方法也在Okio这个类中。我们可以调用sink方法获得一个Sink,调用source方法获得一个Source,而数据的来源或者目的可以是一个File,一个输入或者输出流,一个Socket链接等等。如下
Okio.sink(File file);Okio.appendingSink(File file);//内容可追加Okio.sink(Path path, OpenOption... options);Okio.sink(OutputStream out);Okio.sink(Socket socket);Okio.source(File file);Okio.source(Path path, OpenOption... options);Okio.source(InputStream in);Okio.source(Socket socket);
下面举两个案例来简单说明如何使用Okio。
1、文件读写
//写入数据到文件中Sink sink = Okio.sink(file);BufferedSink bufferedSink = Okio.buffer(sink);bufferedSink.writeUtf8("我是一个中国人");bufferedSink.close();//从文件中读取数据Source source = Okio.source(file);BufferedSource bufferedSource = Okio.buffer(source);String data = bufferedSource.readUtf8();bufferedSource.close();
2、Gzip压缩和读取
//zip压缩GzipSink gzipSink = new GzipSink(Okio.sink(file));BufferedSink bufferedSink = Okio.buffer(gzipSink);bufferedSink.writeUtf8("this is zip file");bufferedSink.flush();bufferedSink.close();//读取zipGzipSource gzipSource = new GzipSource(Okio.source(file));BufferedSource bufferedSource = Okio.buffer(gzipSource);String s = bufferedSource.readUtf8();bufferedSource.close();
- Okio简化处理IO操作
- Okio简化处理I/O操作原理
- Android 善用Okio简化处理I/O操作
- IO操作 IO异常处理
- okio
- Okio精简高效的IO库
- 使用FileUtils简化你的文件操作(commons-io.jar)
- Prototype功能预览五:一个注解简化任意IO操作
- 85、java的IO操作-转换流的简化写法
- Android下的IO库-Okio源码解析(一) 入门
- Android下的IO库-Okio源码解析(贰)
- 数字图像处理--通过矩阵,简化操作(旋转,平移,缩放,切边....)
- dTree动态生成树(后台处理,简化前台操作)
- 2 curses库IO处理--光标操作
- Java_SE08-文本数据IO操作,异常处理
- 文本数据IO操作 、 异常处理
- 43_ajax简化处理
- CLOB处理的处理简化
- Python字符串格式化表达
- 网页背景图片自动适应窗口大小的代码
- HDU5952Counting Cliques(dfs)
- java中arraylist与linkedlist区别
- printf相关
- Okio简化处理IO操作
- JavaBean笔记。
- Android常用提示框(dialog和popuwindow)
- Unity3D开发小贴士(五)Lua调用C#
- oracle之报错:ORA-00054: 资源正忙,要求指定 NOWAIT
- tgz(tar.gz)的压缩和解压
- 工厂模式
- 图片选择器编写
- 滚动加载图片