Java源码-InputStream

699 阅读2分钟

InputStream是一个抽象类,是所有字节输入流的超类,它的子类必须始终提供一种返回下一个输入字节的方法。

继承体系

public abstract class InputStream implements Closeable {
    public void close() throws IOException {}
}

public interface Closeable extends AutoCloseable {
    public void close() throws IOException;
}

public interface AutoCloseable {
     void close() throws Exception;
}
  • AutoCloseable在java.lang包下,定义了释放资源close方法,在try -with-resources语句管理的对象上会自动调用此方法,强烈建议AutoCloseable的实现者使其close方法成为幂等。

  • Closeable在java.io包下,对AutoCloseable#close方法进行了重写,释放IO资源,其close方法成为幂等。

  • InputStream未实现close方法,交由其子类方法来实现。

静态变量

private static final int MAX_SKIP_BUFFER_SIZE = 2048;
  • MAX_SKIP_BUFFER_SIZE声明跳过输入流中字节时使用的最大缓冲区的大小。

主要方法

  • available方法

    public int available() throws IOException {
        return 0;
    }
    
    • 在不阻塞的情况下可以从此输入流读取(或跳过)的字节数的估计,当到达输入流的末尾时为0 。
    • 本类中返回值始终为0,子类应当实现该方法,然而许多子类尚未实现,所以使用该方法时需要注意。
  • close方法

    public void close() throws IOException {}
    
    • 释放此输入流以及该流关联的所有系统资源,由子类实现。
  • mark方法

    public synchronized void mark(int readlimit) {}
    
    • 此方法线程安全。
    • 标记此输入流中的当前位置。
    • readlimit参数告诉此输入流允许在标记位置无效之前读取多少字节。
  • markSupported方法

    public boolean markSupported() {
        return false;
    }
    
    • 如果此流实例支持mark和reset方法,则为true 否则为false 。
    • 默认实现不支持。
  • read方法

    public abstract int read() throws IOException;
    
    public int read(byte b[]) throws IOException {
        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) {
            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;
    }
    
    • 参数:b -读取数据的缓冲区,off –数组b中写入数据的起始偏移量,len –读取的最大字节数。
    • 读入缓冲区的总字节数,如果由于到达流的末尾而没有更多数据,则返回-1 。
    • 我们通常使用该方法返回值不等于-1来循环读取数据。
  • reset方法

    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }
    
    • 将此流重新定位到最后一次在此输入流上调用mark方法的位置。
    • 如果子类没有实现该方法,默认抛异常。
  • skip方法

    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;
    }
    
    • 参数:n-要跳过的字节数。
    • 返回值:实际跳过的字节数。

InputStreamDemo

public void  InputStreamDemo(InputStream in){
   try {
      //输入流字节数
      int available = in.available();
      System.out.println(available);
      //是否支持mark和reset方法
      boolean b = in.markSupported();
      System.out.println(b);
      if(b){
         int readlimit = 10 ;
         in.mark(readlimit);
         in.reset();
      }
      //跳过一个字节
      long n = 1L ;
      in.skip(n);
      //读入缓冲区的总字节数
      int len = 0 ;
      //缓冲区
      byte[] bff = new byte[1024];
      //循环读取到缓冲区
      while((len = in.read(bff)) != -1){
         for (byte item : bff) {
            System.out.println((char)item);
         }
      }
   }catch(IOException e){
      e.printStackTrace();
   }finally {
      try {
         //关闭输入流
         in.close();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}