InputStream和OutputStream是Java IO API 中所有字节输入/输出流的基类,是一个抽象类,实现了Cloaseable接口
InputStream 最核心的是三个read方法:
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException;
public int read(byte b[], int off, int len) throws IOException;
第一个是抽象的read方法是后两个方法的基础,后两个方法均调用了该方法,该方法必须由子类实现。该方法表示一次读取一个字节的数据,如果已经到达流末尾则返回-1
第二个方法等效于第三个方法read(b, 0, b.length)
第三个方法表示一次可以最多读取len个数据字节缓存在byte数组b中,但读取的字节也可能小于该值,以整数的形式返回实际读取的字节数,如果已经到达流末尾则返回-1
public int read(byte b[], int off, int len) throws IOException;
/*
* b[]是用于缓冲数据的字节数组
* len是最大读取的字节数,但读取的字节也可能小于该值
* off是b[]写入数据时的初始偏移量
*/
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
// 缓存字节数组 未实例化 抛出NullPointException
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
/* off偏移量小于0
* 或 最大读取字节数小于0
* 或 最大读取字节数超出了b[]数组长度减去偏移长度
* (即b[]缓冲数组无法保存本次读取的字节数据)
* 抛出IndexOutOfBoundsException
*/
throw new IndexOutOfBoundsException();
} else if (len == 0) {
//最大读取字节数是0 直接返回0
return 0;
}
// 读取第一个字节的数据
int c = read();
// 如果到达流末尾了则直接返回-1, 即该文件是个空文件
if (c == -