package java.io;
//此抽象类是表示字节输入流的所有类的超类。
//需要定义 InputStream 子类的应用程序必须总是提供返回下一个输入字节的方法。
public abstract class InputStream implements Closeable {
//最大跳过缓冲区大小用于确定跳过时要使用的最大缓冲区大小。
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
/**
* 从输入流中读取下一个数据的字节。这个字节的值用一个0到255的int类型返回。
* 如果输入流已经到尾了,就会返回-1。这个方法一直阻塞到
* 有数据输入,输入流检测完成,或者抛出异常。
*
* <p> 一个子类必须实现此方法。
*
* @return 下一个数据的字节,当返回-1时候表示已经到尾了。
* @exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException {
//这个方法默认偏移量为0,读取的长度就是入参字节数组的长度。
return read(b, 0, b.length);
}
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) {
//如果偏移量小于0,或者要读取的长度小于0,或者读取的长度大于实际可存储的长度。
//直接报下标超出异常。
throw new IndexOutOfBoundsException();
} else if (len == 0) {
//如果要读取的长度是0,则直接返回。
return 0;
}
//先做第一次获取,如果已经到底了直接返回,不做后面的步骤了
//使用子类实现的read()方法,直接获取字节。
int c = read();
if (c == -1) {
return -1;
}
//放在偏移后的第一位
b[off] = (byte)c;
int i = 1;//因为已经读取了一个了,这里设为1。
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
//如果输入流已经结束了就break退出
break;
}
//把它放在偏移后的位置。
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
//返回已经读取的字节数量
return i;
}
/**
* 从输入流中跳过并且丢弃指定的字节数,由于各种各样的原因,这个方法可能最终会跳过一些比较小的字节数,例如0。
* 这可能是由于以下几种情况造成的。
* 在指定字节数被跳过之前,到达文件的末尾只是其中的一种可能。
* 实际跳过的字节数会被返回。
* 如果需要跳过的字节是负数,这个类的这个方法总是返回0,并且没有字节被跳过。
* 子类可以用不同的方式处理负值。
*
* 此类的 skip 方法创建一个 byte 数组,然后重复将字节读入其中,直到读够 n 个字节或已到达流末尾为止。
* 建议子类提供此方法更为有效的实现。
* 例如,可依赖搜索能力的实现。
*
* @param n 需要跳过的字节数
* @return 实际已经跳过的字节数
* @exception IOException 如果输入流没有办法获取或者发生其他的I/O错误。
*/
public long skip(long n) throws IOException {
//记录还需要跳过多少个字节
long remaining = n;
//记录每次跳过了多少个字节
int nr;
//非法输入不做任何操作,返回0。
if (n <= 0) {
return 0;
}
//一次最大只能跳过MAX_SKIP_BUFFER_SIZE这个数值。
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;
}
//关闭资源
public void close() throws IOException {}
//标记位置
public synchronized void mark(int readlimit) {}
//重新回到标记位置
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
//标记功能是否可用
public boolean markSupported() {
return false;
}
}
InputStream源码解析
最新推荐文章于 2024-06-12 17:30:51 发布