InputStream源码解析

mac2024-01-28  43

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; } }
最新回复(0)