javaIO -- InputStream和OutStream

一、简介

  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将会将字节数组的数据写入

原文地址:https://www.cnblogs.com/FondWang/p/11825665.html