okio:定义简短高效

Okio 是 Square 公司为优化 IO 操作而开发的库,它针对 Java 原生 IO 的不足,尤其是内存管理和效率问题进行了改进。Okio 使用独特的双向循环链表和 Segment 结构实现高效的数据缓存,减少中间拷贝过程,提高数据传输速度。本文深入解析 Okio 中的核心概念,包括 Source、Sink、Buffer、Segment 和 SegmentPool,并探讨其实现的 GZIP 压缩与解压功能。通过对 Okio 的理解,可以更好地利用其在实际项目中的高性能特性。
摘要由CSDN通过智能技术生成
本篇目录

一、前言

okio是大名鼎鼎的square公司开发出来的,其是okhttp的底层io操作库,既然已经有java原生的io库为什么还要自己费尽开发一套呢?java原生的io操作存在很多问题,比如读写阻塞,内存管理并不高效,体系臃肿,api调用不精简,以上我个人认为okio改进最大的地方是内存管理方面,比如我们拷贝数据java原生io数据转移大体过程如下:

而okio中过程如下:

少了一个中间数据拷贝的过程,这样效率会提升很多,并且okio中数据缓存的处理更是精心设计的,我觉得这部分才是其精华所在:okio将数据(Buffer)采用双向循环链表的方式组织在一起,并且链表每个结点数据存储在一个个数组(Segment)中,结构如下:

这样的存储结构有很多好处,拷贝数据我们可以直接移动指针而不像原生io那样需要一个个字节拷贝过去,这样会大大提高数据转移的效率。

再来简要看一下API的使用简洁性

向file中写入数据,原生io实现如下:

public static void writeTest(File file) {
    try {
        FileOutputStream fos = new FileOutputStream(file);
        OutputStream os = new BufferedOutputStream(fos);
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("write string by utf-8.\n");
        dos.writeInt(1234);
        dos.flush();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

用okio实现:

public static void writeTest(File file) {
    try {
        Okio.buffer(Okio.sink(file))
            .writeUtf8("write string by utf-8.\n")
            .writeInt(1234).close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

以上demo很好的体现了okio api的简洁性。

通过以上比较你应该能感受到okio的强大之处,但是也要明白一点okio也是完全基于原生InputStream与OutputStream来进行封装的,并没有完全舍弃原生io,可以理解为对原生io的封装扩展,重点优化了缓存部分,至于缓存部分后续分析完源码你会有更深入的理解。

另外okio提供数据访问的超时机制,访问资源可以控制时间。

okio的源码比较简短,建议有时间好好阅读一下。

二、顶级接口Source与Sink

Source与Sink是Okio中的输入流接口和输出流接口,对应原生IO的InputStream和OutputStream。

先看下Source源码:

public interface Source extends Closeable {
 
  long read(Buffer sink, long byteCount) throws IOException;

  Timeout timeout();

  @Override void close() throws IOException;
}

很简单就定义了几个方法,读数据到sink中以及关闭资源的方法,至于timeout方法暂时先不用管,后面提超时机制的时候会分析。

Sink源码:

public interface Sink extends Closeable, Flushable {

  void write(Buffer source, long byteCount) throws IOException;

  @Override void flush() throws IOException;

  Timeout timeout();

  @Override void close() throws IOException;
}

同样比较简单,没什么好说的,自己看一下就可以了。

三、BufferedSource与BufferedSink

BufferedSource与BufferedSink同样是两个接口类,分别继承Source与Sink接口,BufferedSource与BufferedSink是具有缓存功能的接口,各自维护了一个buffer,同时提供了很多实用的api调用接口,平时我们使用也主要是调用这两个类中定义的方法。

BufferedSink类:

public interface BufferedSink extends Sink {
  /** Returns this sink's internal buffer. */
  Buffer buffer();

  BufferedSink write(ByteString byteString) throws IOException;

  BufferedSink write(byte[] source) throws IOException;

  BufferedSink write(byte[] source, int offset, int byteCount) throws IOException;

  long writeAll(Source source) throws IOException;

  BufferedSink write(Source source, long byteCount) throws IOException;

  BufferedSink writeUtf8(String string) throws IOException;

  BufferedSink writeUtf8(String string, int beginIndex, int endIndex) throws IOException;

  /** Encodes {@code codePoint} in UTF-8 and writes it to this sink. */
  BufferedSink writeUtf8CodePoint(int codePoint) throws IOException;

  /** Encodes {@code string} in {@code charset} and writes it to this sink. */
  BufferedSink writeString(String string, Charset charset) throws IOException;

  BufferedSink writeString(String string, int beginIndex, int endIndex, Charset charset)
      throws IOException;

  /** Writes a byte to this sink. */
  BufferedSink writeByte(int b) throws IOException;

  BufferedSink writeShort(int s) throws IOException;

  BufferedSink writeShortLe(int s) throws IOException;

  BufferedSink writeInt(int i) throws IOException;

  BufferedSink writeIntLe(int i) throws IOException;

  BufferedSink writeLong(long v) throws IOException;

  BufferedSink writeLongLe(long v) throws IOException;

  BufferedSink writeDecimalLong(long v) throws IOException;

  BufferedSink writeHexadecimalUnsignedLong(long v) throws IOException;

  @Override void flush() throws IOException;

  BufferedSink emit() throws IOException;

  BufferedSink emitCompleteSegments() throws IOException;

  /** Returns an output stream that writes to this sink. */
  OutputStream outputStream();
}

就是定义了一些写方便的方法,其中emit()与flush()方法刚接触同学可能有些生疏,去看下源码中注释就明白了,其余都比较简单了,不熟悉可以看下注释,老外写代码挺注重注释的~

BufferedSource类源码这里只看一部分了,与BufferedSink对应:

public interface BufferedSource extends Source {

  /** Returns this source's internal buffer. */
  Buffer buffer();

  /**
   * Returns when the buffer contains at least {@code byteCount} bytes. Throws an
   * {@link java.io.EOFException} if the source is exhausted before the required bytes can be read.
   */
  void require(long byteCount) throws IOException;

  /**
   * Returns true when the buffer contains at least {@code byteCount} bytes, expanding it as
   * necessary. Returns false if the source is exhausted before the requested bytes can be read.
   */
  boolean request(long byteCount) throws IOException;

  /** Removes a byte from this source and returns it. */
  byte readByte() throws IOException;

  short readShort() throws IOException;

  short readShortLe() throws IOException;

  long readLong() throws IOException;

  /** Removes all bytes bytes from this and returns them as a byte string. */
  ByteString readByteString() throws IOException;
  
  /** Removes {@code byteCount} bytes from this and returns them as a byte array. */
  byte[] readByteArray(long byteCount) throws IOException;

  int read(byte[] sink) throws IOException;

  void readFully(byte[] sink) throws IOException;

  int read(byte[] sink, int offset, int byteCount) throws IOException;

  long readAll(Sink sink) throws IOException;

  String readUtf8() throws IOException;

  String readUtf8Line() throws IOException;

  /** Returns an input stream that reads from this source. */
  InputStream inputStream();
}

这里只是列出了部分定义的方法,大体看一下就可以了,就是各种读的方法。

四、 RealBufferedSink 和 RealBufferedSource

上面提到的都是接口类,具体的实现类分别是RealBufferedSink和 RealBufferedSource ,其实这两个类也不算具体实现类,只是Buffer类的代理类,具体功能都在Buffer类里面实现的。

RealBufferedSink类部分源码:

final class RealBufferedSink implements BufferedSink {
  public final Buffer buffer = new Buffer();
  public final Sink sink;
  boolean closed;

  RealBufferedSink(Sink sink) {
    if (sink == null) throw new NullPointerException("sink == null");
    this.sink = sink;
  }

  @Override public Buffer buffer() {
    return buffer;
  }

  @Override public void write(Buffer source, long byteCount)
      throws IOException {
    if (closed) throw new IllegalStateException("closed");
    //调用buffer的write方法
    buffer.write(source, byt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值