android 文件 IO,固然也是 Java IO。廖廖几百字,来讲清楚文件 IO 究竟是什么。经过对一些基本概念的理解以及 Java IO 中其余的一些必要性知识的理解,来透彻的理解 Java IO.java
字节:代码里表示就是 byteandroid
字符:代码里单独表示就是 char,byte 不能表示一个字符。dom
字符编码:字符要用多少个字节表示,以包括如何表示。就是传说中的 utf-8,ansi,utf-16be,gbk 等异步
文件编码:也就是文件存储时采用何种字符编码。存储时采用何种编码,那读取时也必须采用相应的编码。不然在碰到非英文字符的时候,就会碰到不怀好意的乱码问题。函数
理解了上面的概念,也就是理解了,为何 Java 的 IO 会区分字节流与字符流了。学习
能够这么说,最基本的字节流分别是 读 - FileInputStream(FileWriter) ,写 - FileOutputStream (FileReader)。这两个类能够理解是真正与 “文件 - File” 发生关系的。这两个类中包含了更底层的 IO 处理,例如调用 IoBridge.open(),IoBridge.read(),IoBrige.write()以及IoBridge.closeAndSignalBlockedThreads()等桥接方法调用。而这些底层的类又是经过更底层的 Posix 类,再经过 JNI 调用到 C 层实现(C 层并无用 C语言的fread()等函数,而是直接调用的系统调用 read()),最后实现文件的读与写等文件相关的操做。因此流是对底层IO相关的系统调用的一个细节封装。编码
Java中定义了流的概念,输入流或者输出流,且不可逆不可任意跳转,从源码上来看都是出于设计上的考量。参考 RandomAccessFile 的实现,其之因此可以随机访问文件,其实就是经过调用了 Libcore.os.lseek() 来实现。固然,普通的流也有调用到 Libcore.os.lseek(),就是 skip()方法,而没有像 RandomAccessFile 同样提供了上层的 seek() 方法。spa
为了你们使用上的方便,如读一个 int 须要分红 4 个字节去读,而且作一次计算,Java中提供了 DataInputStream/DataOutputStream,其就是装饰了一下,底层的文件 IO 操做均是由 FileInputStream/FileOutStream 来实现的。线程
public final int readInt() throws IOException { 387 // b/30268192 388 // Android-changed: Use read(byte[], int, int) instead of read(). 389 readFully(readBuffer, 0, 4);//读 4 个字节 390 return Memory.peekInt(readBuffer, 0, ByteOrder.BIG_ENDIAN);//将 4 个字节转换成 Int 值 391 } /** * 分大小端转成 Int **/ public static int peekInt(byte[] src, int offset, ByteOrder order) { 46 if (order == ByteOrder.BIG_ENDIAN) { 47 return (((src[offset++] & 0xff) << 24) | 48 ((src[offset++] & 0xff) << 16) | 49 ((src[offset++] & 0xff) << 8) | 50 ((src[offset ] & 0xff) << 0)); 51 } else { 52 return (((src[offset++] & 0xff) << 0) | 53 ((src[offset++] & 0xff) << 8) | 54 ((src[offset++] & 0xff) << 16) | 55 ((src[offset ] & 0xff) << 24)); 56 } 57 }
BufferedInputStream/BufferedOutputStream 就更简单了,就是在 IO 前先将数据存入或者写出到byte[] buffer 中,外加一个 count 计数器记录下写入与写出的字节个数。而真正与文件发生 IO 的仍是 FileInputStream/FileOutputStream设计
BufferedWriter/BufferedReader 是相似的,只不过它的 buf 是 char[] ,而不是 byte[]。同时,它也用了一个 pos 做为下标计数器。
管道流,单独放在最后讲,并非由于它有多么的高大上,由于惭愧的是,我在实际编码当中历来没有用到过。但这两个类所涉及的设计思想很是值得咱们学习。
做用:用于两个不一样的线程之间进行通讯
文件IO:这两个类是没有文件 IO 的。写入读出都是在同一个 byte[] buffer 内
封装:PipedOutputStream 封装了 PIpedInputStream,PipedInputStream 封装了 byte[] buffer
buffer:这是一个循环 buffer ,分别用了 in 表示下一个要写的位置,out 表示下一个要读的位置。读的最大范围为 [out,int) 左闭右开区间,写的最大范围为 [in,out)
in 为 -1 表示空 buffer,读线程阻塞等待
in == empty 表示 buffer 满,写线程阻塞等待
但须要注意的是,无论是读待仍是写等待,最多只会等 3 秒钟,且是每隔一次一秒的。
Java 中还有一些其余相关的流,如 PrintStream/PrintWriter ,其也就是多了一些封装帮助咱们更方便更快捷的完成代码编写,从而摒弃一些复杂的运算,专心处理业务逻辑便可。
Java IO 的知识点还不少,上面都是一些最基础的东西,但掌握了上面这些比较基础的东西,那其余复杂的东西也就容易掌握了。
Java 还有一类 IO 称为 NIO,其主要目的是为了超大文件,复用IO的异步读写。NIO 的三要素为 Channel,Buffer,Selector。先知道有这么几个东西吧。