| Okio | java.io |
|---|---|
| ByteString | String |
| Buffer | ByteArray |
| Source | InputStream |
| Sink | OutputStream |
| Segment | |
| SegmentPool |
虽然 okio.ByteString 对标的是 java.lang.String,但是它操作的对象却是 String 内部的 ByteArray,相较于 String 的 字符数据 更贴近于 字节数据 的概念
| 类别 | API |
|---|---|
| 字符编码(charset) | utf8() |
| string(charset) | |
| 消息摘要(message digest) | md5() 128-bit |
hmacSha1(key) 160-bit, hmacSha256(key) 256-bit, hmacSha512(key) 512-bit <br> hmac 是额外添加了一个秘钥作为影响因子的 sha |
|
sha1() 160-bit, sha256() 256-bit, sha512() 512-bit |
|
| digest(algorithm) | |
| 基于字节的匹配和查找(而不是字符) | rangeEquals(offset, other ByteString/ByteArray, otherOffset, byteCount) |
| startsWith(ByteString/ByteArray) | |
| endsWith(ByteString/ByteArray) | |
| indexOf(other ByteString/ByteArray, fromIndex) | |
| lastIndexOf(other ByteString/ByteArray, fromIndex) | |
| 其他 | hex() |
| toAsciiLowercase() | |
| toAsciiUppercase() |
SegmentPool),段太大容易造成内存浪费Segment 通过 Segment.prev 和 Segment.next 形成一个环(头尾相连的链表)Segment.limit 是下一次写操作写入的位置,Segment.pos 是下一次读操作读取的位置,正常情况下 0 <= pos <= limit <= max| API | 描述 |
|---|---|
| read/write | 读写各种类型的数据类型 |
| copy()/clone() | 返回一个共享数据的 Buffer <br> 这个就比较有意思了,我们知道 Buffer 用 Segment 对数据进行分片管理(类似于内存的分页),这里并没有真正将数据拷贝一份到另一个 Buffer(要节约内存嘛),而是让另一个 Buffer 里的 Segment 与当前 Buffer 里的 Segment 共享用一个 ByteArray <br> 新的 Segment 可以有自己的 pos 和 limit,可以读但不能写(Segment.owner == false,写入的数据会放到新创建的/自己的 Segment 里去),不然会把别人的数据搞乱,当然 Segment 的持有者是可以写的(Segment.owner == true) <br> 共享了数据的 Segment 不能被 SegmentPool 回收(因为可能别人还在用,而且内部没有计算器指示被多少人持有),它的 Segment.share == true |
| copyTo(Buffer) | 使另一个 Buffer 与当前 Buffer 共享某一段数据 |
| peek() | 返回一个可以重复读的 Source(一般的 Source 跟 InputStream 一样是单向/流式的,不能重复读),但是这个 Buffer 作为 Source 的 backend,已读的数据 Source 也是无法读取的 |
| snapshot(byteCount) | 返回一个 ByteString(上面说过 Okio ByteString 对标 java.lang.String),特别的是它与 Buffer 是共享底层 ByteArray 的(不是共享 Segment,但会使 Segment.shared 置真) <br> ByteString 是不可变的所以它不会修改共享的 ByteArray |
| skip(byteCount) | 跳过 byteCount 字节的数据,使读指针 pos 前进 byteCount 位(已读完的 Segment 将被回收) |
| inputStream() | 把 Buffer 作为输入流的源 |
| outputStream() | 把 Buffer 作为输出流的目的地 |
| copyTo(OutputStream) | 将 Buffer 里的数据拷贝一份到 OutputStream,不移动 Segment.pos(也即不会释放已读数据) |
| writeTo(OutputStream) | 将 Buffer 里的数据写入到 OutputStream,会移动 Segment.pos |
| readFrom(InputStream) | 将 InputStream 里的数据读到 Buffer 里 |
Segment.take()),当一个 Segment 从环里移除不再需要时总是会放回到池里去(Segment.recycle(Segment))SegmentPool 是全局的,内部结构类似于 HashMap(数组 + 链表),只不过数组容量是固定的,通过 tid 决定用哪个链表