一、简介
InputStream 和 OutputStream 对于字节流的输入和输出是作为协议的存在
所以有必要了解下这两个类提供出来的基本约定,这两个类是抽象类,而且基本上没什么实现,都是依赖于子类具体的去实现,但是他是对于其子类 协议纲领一般的存在。
二、InputStream
所有字节输入流的 超类 他是一个抽象类。定义很多抽象方法,比较简单。源码如下
public abstract class InputStream implements Closeable { //用于确定跳跃时使用的最大缓冲区大小。 private static final int MAX_SKIP_BUFFER_SIZE = 2048; //从输入流中读取下一个数据字节。返回的数据为读取到的字节值。也就是直接返回字节值。而下面两个方法是将读取到的字节值放入数组中 public abstract int read() throws IOException; //从输入流中读取若干字节并将其存储到缓冲区数组b中。返回值为读取到的个数 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } //从输入流中读取从off到len长度的数据到字节数组中。返回值为读取到的个数 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个字节的数据 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)); //将跳过的数据,缓存到skipBuffer数组中 if (nr < 0) { break; } remaining -= nr; } return n - remaining; } //返回可读取输入流的数据数量(估计值) public int available() throws IOException { return 0; } //关闭此输入流并释放与此流关联的任何系统资源 public void close() throws IOException {} //标记此输入流中的当前位置。对reset方法的后续调用会将此流重新定位到最后标记的位置,以便后续读取重新读取相同的字节。 public synchronized void mark(int readlimit) {} //将此流重新定位到该输入流上一次调用标记方法时的位置。 public synchronized void reset() throws IOException { throw new IOException("mark/reset not supported"); } //测试这个输入流是否支持标记和重置方法。是否支持标记和重置是特定输入流实例的不变属性。 public boolean markSupported() { return false; }
三、OutStream
所有字节输出流的 超类 他是一个抽象类。源码如下:
//这个抽象类是表示字节输出流的所有类的超类。输出流接受输出字节并将它们发送到某个接收器。
public abstract class OutputStream implements Closeable, Flushable { //将指定的字节写入此输出流 public abstract void write(int b) throws IOException; //从指定的 byte 数组写入此输出流 public void write(byte b[]) throws IOException { write(b, 0, b.length); } //将指定字节数组中从偏移位置off开始到len的bytes写到这个输出流。 public void write(byte b[], int off, int len) throws IOException { if (b == null) { //不能为空 throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { //参数合法 throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } for (int i = 0 ; i < len ; i++) { write(b[off + i]); } } //刷新此输出流并强制写出任何已缓冲的输出字节 public void flush() throws IOException { } //关闭此输出流并释放与此流关联的任何系统资源 public void close() throws IOException { } }
四、总结
* read() 与write(int b) 是根本的读取一个字节或者写入一个字节的方法;
* 其余形式是针对传入字节数组作为参数,以及指定字节数组的偏移量时的一些拓展功能;
* 一旦传递了字节数组作为参数:1. read将会读取数据到字节数组;2. write将会将字节数组的数据写入