Okio源码学习分析,hbuilder开发移动app教程

override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int {

checkOffsetAndCount(sink.size.toLong(), offset.toLong(), byteCount.toLong())

//如果buffer的数据为空,则先调用被装饰的对象(也就是InputStreamSource)将数据读到buffer当中

if (buffer.size == 0L) {

val read = source.read(buffer, Segment.SIZE.toLong())

if (read == -1L) return -1

}

val toRead = minOf(byteCount, buffer.size).toInt()

return buffer.read(sink, offset, toRead)

}

override fun write(source: ByteArray): BufferedSink {

check(!closed) { “closed” }

buffer.write(source)

return emitCompleteSegments()

}

此外,Sink和Source它门还各自有一个支持gzip压缩的实现类GzipSinkGzipSource;一个具有委托功能的抽象类ForwardingSinkForwardingSource;还有一个实现类便是InflaterSource和DeflaterSink,这两个类主要用于压缩,为GzipSink和GzipSource服务,这里就不详细看了。Sink和Source还有其他的类,如HashingSink, HashingSource, 也是装饰者,这里就不一一列举了,其实Okio的Source和Sink装饰者家族类似于java的InputStream和OutStream家族。

Segment

在前面的RealBufferedSourceRealBufferedSink的读写方法中都是调用buffer对象进行操作的,但其实Buffer类的内部读写对象则最终是Segment对象,因此要想了解Buffer的机制首先要了解一下SegmentSegmentBuffer的核心依赖对象,也是Okio中最底层数据的持有者。

在Buffer中的每一个Segment都是双向循环链表中的一个节点,该节点分别拥有指向前驱节点的Segment对象引用以及指向后驱节点的Segment对象引用。而在Segment池中的Segment则是一个单向链表的节点,Segment池持有对下一个Segment节点对象的引用。如果Segment中的字节数据是在buffer和byte string间共享的,那么该Segment对象是不可以被回收的,也是不能修改其中的数据的,除非是它的持有者。

其实Segment的源码注释都写的很清楚了,直接贴出来看一下好了:

/**

  • A segment of a buffer.

  • Each segment in a buffer is a circularly-linked list node referencing the following and

  • preceding segments in the buffer.

  • Each segment in the pool is a singly-linked list node referencing the rest of segments in the

  • pool.

  • The underlying byte arrays of segments may be shared between buffers and byte strings. When a

  • segment’s byte array is shared the segment may not be recycled, nor may its byte data be changed.

  • The lone exception is that the owner segment is allowed to append to the segment, writing data at

  • {@code limit} and beyond. There is a single owning segment for each byte array. Positions,

  • limits, prev, and next references are not shared.

*/

final class Segment {

/** The size of all segments in bytes. */

static final int SIZE = 8192;

/** Segments will be shared when doing so avoids {@code arraycopy()} of this many bytes. */

static final int SHARE_MINIMUM = 1024;

final byte[] data;

/** The next byte of application data byte to read in this segment. */

int pos;

/** The first byte of available data ready to be written to. */

int limit;

/** True if other segments or byte strings use the same byte array. */

boolean shared;

/** True if this segment owns the byte array and can append to it, extending {@code limit}. */

boolean owner;

/** Next segment in a linked or circularly-linked list. */

Segment next;

/** Previous segment in a circularly-linked list. */

Segment prev;

Segment() {

this.data = new byte[SIZE];

this.owner = true;

this.shared = false;

}

Segment(Segment shareFrom) {

this(shareFrom.data, shareFrom.pos, shareFrom.limit);

shareFrom.shared = true;

}

Segment(byte[] data, int pos, int limit) {

this.data = data;

this.pos = pos;

this.limit = limit;

this.owner = false;

this.shared = true;

}

/**

  • Removes this segment of a circularly-linked list and returns its successor.

  • Returns null if the list is now empty.

*/

public @Nullable Segment pop() {

Segment result = next != this ? next : null;

prev.next = next;

next.prev = prev;

next = null;

prev = null;

return result;

}

/**

  • Appends {@code segment} after this segment in the circularly-linked list.

  • Returns the pushed segment.

*/

public Segment push(Segment segment) {

segment.prev = this;

segment.next = next;

next.prev = segment;

next = segment;

return segment;

}

/**

  • Splits this head of a circularly-linked list into two segments. The first

  • segment contains the data in {@code [pos…pos+byteCount)}. The second

  • segment contains the data in {@code [pos+byteCount…limit)}. This can be

  • useful when moving partial segments from one buffer to another.

  • Returns the new head of the circularly-linked list.

*/

public Segment split(int byteCount) {

if (byteCount <= 0 || byteCount > limit - pos) throw new IllegalArgumentException();

Segment prefix;

// We have two competing performance goals:

// - Avoid copying data. We accomplish this by sharing segments.

// - Avoid short shared segments. These are bad for performance because they are readonly and

// may lead to long chains of short segments.

// To balance these goals we only share segments when the copy will be large.

if (byteCount >= SHARE_MINIMUM) {

prefix = new Segment(this);

} else {

prefix = SegmentPool.take();

System.arraycopy(data, pos, prefix.data, 0, byteCount);

}

prefix.limit = prefix.pos + byteCount;

pos += byteCount;

prev.push(prefix);

return prefix;

}

/**

  • Call this when the tail and its predecessor may both be less than half

  • full. This will copy data so that segments can be recycled.

*/

public void compact() {

if (prev == this) throw new IllegalStateException();

if (!prev.owner) return; // Cannot compact: prev isn’t writable.

int byteCount = limit - pos;

int availableByteCount = SIZE - prev.limit + (prev.shared ? 0 : prev.pos);

if (byteCount > availableByteCount) return; // Cannot compact: not enough writable space.

writeTo(prev, byteCount);

pop();

Se

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Okio是一个强大的Java I/O库,用于处理输入和输出流的操作。要下载Okio的jar文件,可以按照以下步骤进行: 1. 在网上的Maven仓库或者其它可靠的软件下载网站上搜索"Okio jar"。 2. 找到适合你的项目的Okio jar文件版本。可以根据你的项目需求选择稳定版本或者最新版本。 3. 点击下载链接并选择合适的下载目录。 4. 下载完成后,将jar文件移动到你的项目目录中的lib文件夹(如果没有lib文件夹,则可以创建一个新的lib文件夹)。 5. 打开你的IDE(如Eclipse、IntelliJ IDEA等),导入下载好的Okio jar文件到你的项目中。 6. 在你的代码中导入Okio库的类或者方法,你就可以开始使用Okio库了。 这些步骤将帮助你下载并且集成Okio jar到你的项目中,让你能够使用Okio库的强大功能。请确保下载和使用的是可靠的版本,并充分理解Okio库的使用方式和文档,以便更好地应用到你的项目中。 ### 回答2: OKIO是一个开源的轻量级IO库,用于在Java平台上进行高效的IO操作。你可以通过下载OKIO jar包来使用它。 首先,你需要找到OKIO的官方网站或是在Maven中央仓库中搜索OKIO。官方网站通常会提供OKIO的jar包下载链接。 一旦找到下载链接,你可以点击下载按钮来获取OKIO的jar包。下载完成后,你将得到一个以.jar结尾的文件。 接下来,将下载的jar包移动到你的Java项目中合适的位置。通常情况下,你可以将它放在项目的lib目录中。 然后,在你的项目中配置构建工具(例如Maven或Gradle)以引入OKIO的依赖。你可以在构建工具的配置文件中添加OKIO的依赖信息,例如Maven的pom.xml文件或Gradle的build.gradle文件。 在配置文件中添加OKIO的依赖信息后,保存文件并进行构建。构建工具将会自动下载并引入OKIO的jar包到你的项目中。 最后,你可以在你的Java代码中使用OKIO库了。可以通过导入OKIO的类来使用它提供的功能,例如读取和写入文件、缓冲区操作等。 总结来说,OKIO的jar包可以通过下载官方网站提供的链接或在构建工具中引入依赖来获取。下载完成后,将jar包放置在项目中合适的位置,并在配置文件中添加依赖信息。完成这些步骤后,你就可以在你的项目中使用OKIO库了。 ### 回答3: Okio是一个高效的Java I/O库,主要用于处理流和字节。要下载Okio JAR文件,可以按照以下步骤进行操作: 1. 打开浏览器并前往Maven仓库的网站(https://mvnrepository.com/)。 2. 在搜索框中输入“Okio”并点击搜索按钮。 3. 在搜索结果中找到最新版本的Okio库,通常以“okio”开头。单击库的版本号以进入详细信息页面。 4. 在详细信息页面中,您将看到有关该库的信息,包括依赖项和Gradle / Maven坐标。 5. 在坐标部分,您可以找到Gradle和Maven的引用代码。根据您的项目构建工具选择适合您的代码。 - 如果您使用Gradle构建项目,请将Gradle代码复制到项目的build.gradle文件中的dependencies部分。 - 如果您使用Maven构建项目,请将Maven代码复制到项目的pom.xml文件中的dependencies部分。 6. 复制引用代码后,保存并关闭文件。 7. 重新构建和编译项目,您的项目将自动下载并使用Okio JAR文件。 请注意,确保您的网络连接良好,以便从Maven仓库成功下载JAR文件。另外,如果您使用的是集成开发环境(IDE),如IntelliJ IDEA或Eclipse,您可以使用IDE的依赖管理工具来搜索并添加Okio库,这更加方便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值