天天看點

JAVA IO源碼學習系列之InputStream

JAVA IO源碼學習系列

## 1.位元組輸入流源碼InputStream介紹##

  1. InpuSteam是位元組輸入流操作的超類(抽象類),定義了基本的一些操作方法,流的操作大概四部分:(1)構造資料流(來源);(2)讀取流;(3)讀取流則需要判斷是否可讀;(4):操作結束要記得關閉;是以主要關注的方法:構造函數(構造資料),available()判斷目前資料是否還能繼續讀取,read()讀取資料,close()結束之後一定關閉相關資源;下面是具體的源碼:
public abstract class InputStream implements Closeable {

    //預設可以跳過的最大範圍
    private static final int MAX_SKIP_BUFFER_SIZE = ;

    //讀取位元組流(子類具體實作)
    public abstract int read() throws IOException;

    //将位元組流寫入具體的位元組數組b[]
    public int read(byte b[]) throws IOException {
        return read(b, , b.length);
    }

    //将位元組流寫入具體的位元組數組b[],從指定的位置讀off,和讀具體的大小len
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
            //如果讀取的大小超過了具體位元組數組的容量大小,則抛出數組越界
        } else if (off <  || len <  || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == ) {
            return ;
        }

        int c = read();
        if (c == -) {
            return -;
        }
        b[off] = (byte)c;

        int i = ;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -) {
                    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 <= ) {
            return ;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > ) {
            nr = read(skipBuffer, , (int)Math.min(size, remaining));
            if (nr < ) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }

    // 傳回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計位元組數。
    public int available() throws IOException {
        return ;
    }
    //關閉此輸入流并釋放與該流關聯的所有系統資源。
    public void close() throws IOException {}

    //在此輸入流中标記目前的位置。
    public synchronized void mark(int readlimit) {}

    将此流重新定位到最後一次對此輸入流調用 mark 方法時的位置。
    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }
    測試此輸入流是否支援 mark 和 reset 方法。
    public boolean markSupported() {
        return false;
    }
           

InputSteam主要抽象了一般的方法,具體實作通過不同的子類,在此就不多做介紹;

神獸出發:

/**
 *        ┌─┐           ┌─┐    
 *   ┌──┘ ┴───────┘ ┴──┐
 *   │                           │
 *   │          ───            │
 *   ███████───███████│+
 *   │                           │+
 *   │         ─┴─             │
 *   │                           │
 *   └───┐         ┌───----┘
 *         │         │
 *         │         │   + +
 *         │         │
 *         │         └──────────────┐
 *         │                        │
 *         │                        ├─┐
 *         │                        ┌─┘
 *         │                        │
 *         └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +
 *         │ ─┤ ─┤       │ ─┤ ─┤
 *         └──┴──┘       └──┴──┘  + + + +
 *                神獸保佑
 *               代碼無BUG!
 */