这里只介绍传统I/O(也就是阻塞的IO)
java IO家族的类实在太多,每个类都有其历史原因所在(所以不要抱怨Java IO难用了)
老习惯,我们首先从顶层父类说起
1、InputStream
这里面有两个特殊的类,是在jdk1.7加的,作用是你可以在try(这里去创建流,不需要在手动关闭流了,十分推荐这种方式,在也不怕流关闭不了){}catch(..){}
1、read() 单字节读取
2、read(byte[]) 批量读取,每次读取byte.length (其实底层也是单字节的形式读取)
3、read(byte[],int off,int len) 虽然也是批量读取,其实底层本质还是单字节读取 ,我们来看下源码
public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = read(); //首先读取一个字节 (这样做的原因是读取到末尾时候就直接返回,提升效率,很好的设计思想) if (c == -1) { return -1; } b[off] = (byte)c; //这里可以看到其实是每次都是一个字节一个字节读取的(这种是传统I/O慢的原因啊) int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; //读取字节的个数 }
其他内部方法就不介绍(因为很少用到)
2、对于输出流OutPutStream() 输出流其实也是单子字节的写
public void write(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } for (int i = 0 ; i < len ; i++) { write(b[off + i]); //每次只写入一个字节 } }