学习扔物线进阶视频课程笔记。IO相关

IO是什么

IO即Input和Output,输入输出,指程序内部和程序外部进行数据交互的过程,程序内部指内存,程序外部指本地文件,或者网络,或者别的进程。

传统IO

也称为BIO,使用流进行单向传输,例如FileInputStream,FileOutputStream。
在流的外面,还可以套别的流,层层嵌套都可以。
Buffered开头的IO流,会给流加一个缓冲。如果是输入流,缓冲的意义是每次多读一些数据放在内存,下次再取数据就不用再和外部交互了;如果是输出流,是把数据先在内存里攒着,攒够一定的数量再一起往外面写,也可以调用flush方法立即将缓冲中的数据写入外部,或者调用close时,也会先将缓冲中的数据写入外部。通过缓冲的方式减少和外部的交互,从而提高效率。
文件流使用完后需要关闭,也可以在try的后面加上括号,然后在括号中初始化closeable对象,可以实现自动关闭,实际开发中推荐使用try括号的方式。

flush和fsync:
现代操作系统中,为了提高磁盘的读写性能,写入磁盘的数据通常会在内核做缓冲
flush是将内存中的缓冲数据立即写入到磁盘的缓冲中,用于保证数据的及时写入。
fsync是强制将磁盘缓冲中的数据真正写入到磁盘物理存储介质上,用于保证数据的持久化。

NIO

使用Channel进行双向传输,如果是网咯交互时,支持非阻塞,文件交互只能是阻塞
NIO使用时强制使用Buffer,比如ByteBuffer是用byte数组实现,创建之后大小不可变,用position和limit来控制数据的位置,写完数据后需要调用flip方法才能进行读数据。
Android中使用MediaCodec做音视频的编解码时会使用到ByteBuffer。
RandomAccessFile实现文件写入,内部也是使用的NIO。

OKIO

单向传输,输入源叫Source,输出目标叫Sink,他的实现原理是对传统IO做了一层包装,让API更好用。
OKIO支持Buffer但不是必须的,而且和NIO的Buffer相比,OKIO的Buffer更好用。
示例代码:

            File file = new File(filesDir, "adb");
            try (BufferedSource bufferedSource = Okio.buffer(
                    Okio.source(context.getAssets().open("adb")));
                    BufferedSink bufferedSink = Okio.buffer(Okio.sink(file))) {
                bufferedSink.writeAll(bufferedSource);
            } catch (IOException e) {
                LogProxy.d(TAG, "initAdbRoot e=" + e);
                e.printStackTrace();
            }