IO 神器 Okio
官方 是这么介绍 Okio 的:
Okio is a library that complements java.io and java.nio to make it much easier to access, store, and process your data. It started as a component of OkHttp, the capable HTTP client included in Android. It’s well-exercised and ready to solve new problems.
重点是这一句它使访问,存储和处理数据变得更加容易,既然 Okio 是对 java.io 的补充,那是否比传统 IO 好用呢?
看下 Okio 这么使用的,用它读写一个文件试试:
// OKio写文件
private static void writeFileByOKio() {
try (Sink sink = Okio.sink(new File(path));
BufferedSink bufferedSink = Okio.buffer(sink)) {
bufferedSink.writeUtf8("write" + "\n" + "success!");
} catch (IOException e) {
e.printStackTrace();
}
}
//OKio读文件
private static void readFileByOKio() {
try (Source source = Okio.source(new File(path));
BufferedSource bufferedSource = Okio.buffer(source)) {
for (String line; (line = bufferedSource.readUtf8Line()) != null; ) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
从代码中可以看出,读写文件关键一步要创建出 BufferedSource
或 BufferedSink
对象。有了这两个对象,就可以直接读写文件了。
Okio为我们提供的 BufferedSink 和 BufferedSource 就具有以下基本所有的功能,不需要再串上一系列的装饰类
现在开始好奇Okio是怎么设计成这么好用的?看一下它的类设计:
在Okio读写使用中,比较关键的类有 Source、Sink、BufferedSource、BufferedSink。
Source 和 Sink
Source
和 Sink
是接口,类似传统 IO 的 InputStream
和 OutputStream
,具有输入、输出流功能。
Sourec
接口主要用来读取数据,而数据的来源可以是磁盘,网络,内存等。
public interface Source extends Closeable {
long read(Buffer sink, long byteCount) throws IOException;
Timeout timeout();
@Override void close() throws IOException;
}
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
接口的扩展处理。Okio 将常用方法封装在 BufferedSource/BufferedSink 接口中,把底层字节流直接加工成需要的数据类型,摒弃 Java IO 中各种输入流和输出流的嵌套,并提供了很多方便的 api,比如 readInt()
、readString()
public interface BufferedSource extends Source, ReadableByteChannel {
Buffer getBuffer();
int readInt() throws IOException;
String readString(long byteCount, Charset charset) throws IOException;
}
public interface BufferedSink extends Sink, WritableByteChannel {
Buffer buffer();
BufferedSink writeInt(int i) throws IOException;
BufferedSink writeString(String string, int beginIndex, int endIndex, Charset charset)
throws IOException;
}
RealBufferedSink 和 RealBufferedSource
上面的 BufferedSource
和 BufferedSink
都还是接口,它们对应的实现类就是 RealBufferedSink
和 RealBufferedSource
了。
final class RealBufferedSource implements BufferedSource {
public final Buffer buffer = new Buffer();
@Override public String readString(Charset charset) throws IOException {
if (charset == null) throw new IllegalArgumentException("charset == null");
buffer.writeAll(source);
return buffer.readString(charset);
}
//...
}
final class RealBufferedSink implements BufferedSink {
public final Buffer buffer = new Buffer();
@Override public BufferedSink writeString(String string, int beginIndex, int endIndex,
Charset charset) throws IOException {
if (closed) throw new IllegalStateException("closed");
buffer.writeString(string, beginIndex, endIndex, charset);
return emitCompleteSegments();
}
//...
}
RealBufferedSource
和 RealBufferedSink
内部都维护一个 Buffer
对象。里面的