转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119997762
本文出自【赵彦军的博客】
Okio是一个库,它补充了java.io和java.nio,使访问、存储和处理数据变得更加容易。
OkHttp的的 io 功能就是 okio 提供的,OkHttp是Android中包含的一个功能强大的HTTP客户端。
github地址:https://github.com/square/okio
api主页:https://square.github.io/okio/
maven地址:https://mvnrepository.com/artifact/com.squareup.okio/okio
依赖引入
implementation group: 'com.squareup.okio', name: 'okio', version: '2.10.0'
/** * 读取文件中的文本 * @param file * @throws IOException */ public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file)) { Buffer buffer = new Buffer(); fileSource.read(buffer, 1024); while (true) { String line = buffer.readUtf8Line(); if (line == null) break; System.out.println(line); } } }
可以看到Source 就相当于 InputStream , 我们看看 Okio.source(file) 的源码
/** Returns a source that reads from `file`. */ @Throws(FileNotFoundException::class) fun File.source(): Source = inputStream().source()
再看看 inputStream() 方法
@kotlin.internal.InlineOnly public inline fun File.inputStream(): FileInputStream { return FileInputStream(this) }
是不是很熟悉,还是 Java IO 那一套。只不过是封装了一层。
我们看看如何创建一个 Source ,它提供了几个方法
Okio.source(InputStream input) Okio.source(File file) Okio.source(Socket socket)
还有一点,okio 最新版本都用kotlin重新实现了,我们看看,上面的代码如果用 kotlin 写是什么样子的。
/** * 读取文件中的文本 * @param file * @throws IOException */ @Throws(IOException::class) fun readFile(file: File) { file.source().use { fileSource -> val buffer = Buffer() fileSource.read(buffer, 1024) while (true) { val line = buffer.readUtf8Line() ?: break println(line) } } }
是不是简介了不少。
我们用了一个 Buffer() 类做缓冲类,我们看看它的继承关系:
class Buffer : BufferedSource, BufferedSink, Cloneable, ByteChannel {
注意事项:
我们定义了 fileSource.read(buffer, 1024)
, 这句话的含义是从文件读数据存入 Buffer 中,最大存入 1024 个字节,返回的是字节个数,如果文件读完了,返回 -1 。
所以完整读取文本文件的代码为:
public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file)) { Buffer buffer = new Buffer(); while (fileSource.read(buffer, 1024) != -1) { while (true) { //一次读一行 String line = buffer.readUtf8Line(); if (line == null) break; System.out.println(line); } } } }
readUtf8Line()
一次读一行,有没有方法一次把 buffer 里面内容读完,也有的 buffer.readUtf8()
, 所以代码可以改成如下
/** * 读取文件中的文本 * * @param file * @throws IOException */ public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file)) { Buffer buffer = new Buffer(); fileSource.read(buffer, 1024); while (fileSource.read(buffer, 1024) != -1) { //一次读完 String line = buffer.readUtf8(); System.out.println(line); } } }
BufferedSource 是一个带有缓冲功能的 Source , 说白了BufferedSource 其实就是内置了一个 Buffer
上面的代码就可以改成:
/** * 读取文件中的文本 * @param file * @throws IOException */ public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file)) { BufferedSource bufferedSource = Okio.buffer(fileSource); while (true) { String line = bufferedSource.readUtf8Line(); if (line == null) break; System.out.println(line); } } }
readUtf8Line()
API读取所有数据,直到下一行分隔符\n、\r\n或文件结尾。它以字符串形式返回该数据,省略结尾的分隔符。当遇到空行时,该方法将返回一个空字符串
。如果没有更多的数据可读取,它将返回null
。
所以我们可以进一步优化代码如下:
/** * 读取文件中的文本 * * @param file * @throws IOException */ public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file)) { BufferedSource bufferedSource = Okio.buffer(fileSource); String line; while ((line = bufferedSource.readUtf8Line()) != null) { System.out.println(line); } } }
所以我们也可以优化成
/** * 读取文件中的文本 * * @param file * @throws IOException */ public void readFile(File file) throws IOException { try (Source fileSource = Okio.source(file); BufferedSource bufferedSource = Okio.buffer(fileSource)) { String line = bufferedSource.readUtf8(); System.out.println(line); } }
最后我们可以封装一个方法来读取文本文件
/** * 读取文件中的文本 * * @param file * @throws IOException */ public String readFile(File file) throws IOException { try (Source fileSource = Okio.source(file); BufferedSource bufferedSource = Okio.buffer(fileSource)) { return bufferedSource.readUtf8(); } }
甚至可以更近一步,再简介一下:
/** * 读取文件中的文本 * * @param file * @throws IOException */ public String readFile(File file) throws IOException { try (BufferedSource bufferedSource = Okio.buffer(Okio.source(file))) { return bufferedSource.readUtf8(); } }
kotlin 版本如下:
@Throws(IOException::class) fun readFile(file: File): String? { file.source().buffer().use { bufferedSource -> return bufferedSource.readUtf8() } }
是不是很简洁。
如果文件不存在,会自动创建文件
/** * 把文本写入文件 * @param file * @throws IOException */ public void writeFile(String content, File file) throws IOException { try (Sink sink = Okio.sink(file); BufferedSink bufferedSink = Okio.buffer(sink)) { bufferedSink.write(content.getBytes()); //写字节 } }
除此之外,还有其他写方法:
bufferedSink.write(byte[] bytes) bufferedSink.writeUtf8(String string) bufferedSink.writeAll(Source source) bufferedSink.write(ByteString byteString)
我们来实现一个读文本,然后再写文本的代码
public class Test { public static void main(String[] args) { Test test = new Test(); try { //从文件读取文本 String string = test.readFile(new File("/Users/xmly/workspace/web1/src/main/aa.txt")); //写文本到文件 test.writeFile(string, new File("/Users/xmly/workspace/web1/src/main/aa1.txt")); } catch (IOException e) { e.printStackTrace(); } } /** * 读取文件中的文本 * * @param file * @throws IOException */ public String readFile(File file) throws IOException { try (BufferedSource bufferedSource = Okio.buffer(Okio.source(file))) { return bufferedSource.readUtf8(); } } /** * 把文本写入文件 * * @param file * @throws IOException */ public void writeFile(String content, File file) throws IOException { try (Sink sink = Okio.sink(file); BufferedSink bufferedSink = Okio.buffer(sink)) { bufferedSink.write(content.getBytes()); } } }
public class Test { public static void main(String[] args) { Test test = new Test(); try { //从文件读取文本 File file1 = new File("/Users/xmly/Desktop/1234.jpeg"); File file2 = new File("/Users/xmly/workspace/web1/src/main/aa1.jpeg"); test.copyFile(file1, file2); } catch (IOException e) { e.printStackTrace(); } } /** * 复制文件 * * @param file1 * @param file2 * @throws IOException */ public void copyFile(File file1, File file2) throws IOException { try (BufferedSource bufferedSource = Okio.buffer(Okio.source(file1)); BufferedSink bufferedSink = Okio.buffer(Okio.sink(file2))) { bufferedSink.writeAll(bufferedSource); } } }
相比java IO , Okio 简直是神器,太简洁,太牛B了