vlambda博客
学习文章列表

通过JDK源码学习InputStream详解

java开发全栈
一枚全栈开发大叔,每周分享python/java软件开发实战技术文章,分享编程前端后端开发测试技术,现在关注即可免费领取编程开发最新资料哦!
8篇原创内容
Official Account


通过JDK源码学习InputStream详解


通过JDK源码学习InputStream详解

--java.lang.Object --java.io.InputStream


类定义

public abstract class InputStream implements Closeable


InputStream 被定为 public 且 abstract 的类,实现了Closeable接口。

Closeable 接口表示 InputStream 可以被close,接口定义如下:

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


主要属性

private static final int MAX_SKIP_BUFFER_SIZE = 2048; private static final int DEFAULT_BUFFER_SIZE = 8192; private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;


通过JDK源码学习InputStream详解


通过JDK源码学习InputStream详解

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;}


通过JDK源码学习InputStream详解

public byte[] readAllBytes() throws IOException { byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; int capacity = buf.length; int nread = 0; int n; for (;;) { while ((n = read(buf, nread, capacity - nread)) > 0) nread += n; if (n < 0) break; if (capacity <= MAX_BUFFER_SIZE - capacity) { capacity = capacity << 1; } else { if (capacity == MAX_BUFFER_SIZE) throw new OutOfMemoryError("Required array size too large"); capacity = MAX_BUFFER_SIZE; } buf = Arrays.copyOf(buf, capacity); } return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);}


通过JDK源码学习InputStream详解

public int readNBytes(byte[] b, int off, int len) throws IOException { Objects.requireNonNull(b); if (off < 0 || len < 0 || len > b.length - off) throw new IndexOutOfBoundsException(); int n = 0; while (n < len) { int count = read(b, off + n, len - n); if (count < 0) break; n += count; } return n;}


通过JDK源码学习InputStream详解

public int available() throws IOException { return 0; }


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;}


close方法

此方法用于关闭输入流,并且释放相关资源 。

public void close() throws IOException {}


transferTo方法

从输入流中按顺序读取全部字节并且写入到指定的输出流中,返回值为转移的字节数。转移过程中可能会发生不确定次的阻塞,阻塞可能发生在 read 操作或 write 操作。

主要逻辑是用 while 循环不断调用 read 方法操作读取字节,然后调用输出流的 write 方法写入,直到读取返回-1,即达到结尾。最后返回转移的字节数。

public long transferTo(OutputStream out) throws IOException { Objects.requireNonNull(out, "out"); long transferred = 0; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int read; while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) { out.write(buffer, 0, read); transferred += read; } return transferred;}


markSupported方法

是否支持 mark 和 reset 操作,这里直接返回 false,子类根据实际重写该方法。

public boolean markSupported() { return false;}


mark方法

标记输入流当前位置,与之对应的是 reset 方法,通过他们之间的组合能实现重复读取操作。另外它会传入 readlimit 参数,它用于表示该输入流中在执行 mark 操作后最多可以读 readlimit 个字节后才使 mark 的位置失效。

可以看到 InputStream 的 mark 方法是什么都不做的,子类中再具体实现。

public synchronized void mark(int readlimit) {}


reset方法

与 mark 方法对应,它可以重置输入流的位置到上次被 mark 操作标识的位置。InputStream 的 reset 方法直接抛出一个 IOException,子类中根据实际情况实现。

public synchronized void reset() throws IOException { throw new IOException("mark/reset not supported");}


总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对"java开发全栈"的支持。