一.概述
是所有字节输入流的超类
二.源码
// jdk7
package java.io;
/**
* 字节输入流的所有类的超类
* @since JDK1.0
*/
public abstract class InputStream implements Closeable {
// 用于确定skip时要使用的最大缓冲区大小。
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
/**
* 从输入流中读取数据的下一个字节。
* 在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。
*
* @return 返回下一个字节数据,为0到255范围内的int值
* 如果已经到达流末尾而没有可用的字节,则返回值 -1。
* @exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;
/**
* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
* 相当于read(b, 0, b.length)
* @param b 存储读入数据的缓冲区
* @return 读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* 将输入流中最多 len 个数据字节读入 byte 数组。
* 尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。
*
* @param b 读入数据的缓冲区
* @param off 数据写入缓冲区b[]中的开始下标off
* @param len 要读取的最大字节数.
* @return 读入缓冲区的总字节数;如果因为已到达流末尾而不再有数据可用,则返回 -1。
*/
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;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
/**
* 跳过和丢弃此输入流中数据的 n 个字节。
* 出于各种原因,skip 方法结束时跳过的字节数可能小于该数,也可能为 0
*
* @param n 要跳过的字节数
* @return 跳过的实际字节数
*/
public long skip(long n) throws IOException {
// 需要跳过的字节数
long remaining = n;
int nr;
if (n <= 0) {
return 0;
}
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0) {
// 实际字节数
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
/**
* 返回可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0。
* 如上传本地文件,通过FileINputStream读取返回文件具体大小
*/
public int available() throws IOException {
return 0;
}
/**
* 关闭此输入流并释放与该流关联的所有系统资源
* InputStream 的 close 方法不执行任何操作
*/
public void close() throws IOException {}
/**
* 在此输入流中标记当前的位置
*
* mark 的常规协定是:如果方法 markSupported 返回 true,那么输入流总是在调用 mark 之后记录所有读取的字节,
* 并时刻准备在调用方法 reset 时(无论何时),再次提供这些相同的字节。
* 但是,如果在调用 reset 之前从流中读取多于 readlimit 的字节,则不需要该流记录任何数据。
*
* mark就像书签一样,用于标记,以后再调用reset时就可以再回到这个mark过的地方。
* mark方法有个参数readlimit,通过这个整型参数,你告诉系统,希望在读出这么多个字符之前,这个mark保持有效。
* 比如说mark(10),那么在read()读取10个以内的字符时,reset()操作后可以重新读取已经读出的数据,
* 如果已经读取的数据超过10个,那reset()操作后,就不能正确读取以前的数据了,因为此时mark标记已经失效。
*
* InputStream 的 mark 方法不执行任何操作。
*
* @param readlimit 在标记位置失效前可以读取字节的最大限制
*/
public synchronized void mark(int readlimit) {}
/**
* 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。
* reset 的常规协定是:
* 如果方法 markSupported 返回 true,那么:
* 如果创建流以后未调用方法 mark,或最后调用 mark 以后从该流读取的字节数大于最后调用 mark 时的参数,则可能抛出 IOException。
* 如果未抛出这样的 IOException,则将该流重新设置为这种状态:最近一次调用 mark 以后(如果未调用过 mark,则从文件开头开始)读取的所有字节将重新提供给 read 方法的后续调用者,后跟任何从调用 reset 时起将作为下一输入数据的字节。
* 如果方法 markSupported 返回 false,那么:
* 对 reset 的调用可能抛出 IOException。
* 如果未抛出 IOException,则将该流重新设置为一种固定状态,该状态取决于输入流的特定类型及其创建方式。提供给 read 方法后续调用者的字节取决于特定类型的输入流。
* 除了抛出 IOException 之外,类 InputStream 的方法 reset 不执行任何操作。
*
*/
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
/**
* 测试此输入流是否支持 mark 和 reset 方法。
* 是否支持 mark 和 reset 是特定输入流实例的不变属性。
* InputStream 的 markSupported 方法返回 false。
*/
public boolean markSupported() {
return false;
}
}