Java 日看一類(44)之IO包中的PipedReader類

該類無引入包

繼承自Reader類


該類的類頭註釋如下:(我見過最簡潔的

 Piped character-input streams.

大意如下:

管道字符輸入流



該類含有如下的成員變量:

對應得輸出流標誌位(是否關閉

boolean closedByWriter = false;

對應讀取流關閉標誌位(就是自己,感覺這裏也該加上volaile

boolean closedByReader = false;

連接狀態

boolean connected = false;

讀取線程

Thread readSide;

寫入線程

Thread writeSide;

默認緩衝區大小

private static final int DEFAULT_PIPE_SIZE = 1024;

緩衝區

char buffer[];

寫入偏移量

int in = -1;

讀取偏移量

int out = 0;


該類含有如下的成員方法:

構造函數(與給定的寫出管道鏈接,使用默認大小緩衝區

public PipedReader(PipedWriter src) throws IOException {
    this(src, DEFAULT_PIPE_SIZE);
}

構造函數(與給定的寫出管道連接,使用指定大小緩衝區

public PipedReader(PipedWriter src, int pipeSize) throws IOException {
    initPipe(pipeSize);
    connect(src);
}

默認構造函數(暫無鏈接,默認大小

public PipedReader() {
    initPipe(DEFAULT_PIPE_SIZE);
}

構造函數(暫無鏈接,給定大小

public PipedReader(int pipeSize) {
    initPipe(pipeSize);
}

管道初始化(初始化緩衝區

private void initPipe(int pipeSize) {
    if (pipeSize <= 0) {
        throw new IllegalArgumentException("Pipe size <= 0");
    }
    buffer = new char[pipeSize];
}

連接管道

public void connect(PipedWriter src) throws IOException {
    src.connect(this);
}

接收單個字符數據進管道

synchronized void receive(int c) throws IOException {
    if (!connected) {//檢查連接狀態
        throw new IOException("Pipe not connected");
    } else if (closedByWriter || closedByReader) {//檢測是否有一段關閉
        throw new IOException("Pipe closed");
    } else if (readSide != null && !readSide.isAlive()) {//檢測讀取線程活動性
        throw new IOException("Read end dead");
    }

    writeSide = Thread.currentThread();
    while (in == out) {//當前緩衝區已滿,暫時無法寫入
        if ((readSide != null) && !readSide.isAlive()) {
            throw new IOException("Pipe broken");
        }
        /* full: kick any waiting readers */
        notifyAll();//喚醒所有掛起線程(讀取線程
        try {
            wait(1000);//掛寫入線程
        } catch (InterruptedException ex) {
            throw new java.io.InterruptedIOException();
        }
    }
    if (in < 0) {//緩衝爲空
        in = 0;
        out = 0;
    }
    buffer[in++] = (char) c;//存寫入數據
    if (in >= buffer.length) {//循環數組修改偏移量
        in = 0;
    }
}

接收字符數組(對上一個函數的循環調用

synchronized void receive(char c[], int off, int len)  throws IOException {
    while (--len >= 0) {
        receive(c[off++]);
    }
}

當寫入端數據全部傳輸完後,喚醒讀取線程,關閉管道

synchronized void receivedLast() {
    closedByWriter = true;
    notifyAll();//喚醒所有讀取線程
}

讀取字符數據

public synchronized int read()  throws IOException {
    if (!connected) {//管道連接狀態
        throw new IOException("Pipe not connected");
    } else if (closedByReader) {//Reader端是否關閉
        throw new IOException("Pipe closed");
    } else if (writeSide != null && !writeSide.isAlive()//檢測現在是否有程序在寫入
               && !closedByWriter && (in < 0)) {
        throw new IOException("Write end dead");
    }

    readSide = Thread.currentThread();//寫入線程綁定
    int trials = 2;//兩次機會
    while (in < 0) {//當前爲空
        if (closedByWriter) {//且寫入端已關閉
            /* closed by writer, return EOF */
            return -1;
        }
        if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
            throw new IOException("Pipe broken");
        }
        /* might be a writer waiting */
        notifyAll();//喚醒所有線程(寫線程
        try {
            wait(1000);//睡讀取線程
        } catch (InterruptedException ex) {
            throw new java.io.InterruptedIOException();
        }
    }
    int ret = buffer[out++];//讀取數據
    if (out >= buffer.length) {
        out = 0;
    }
    if (in == out) {//讀取完畢,緩衝區爲空
        /* now empty */
        in = -1;
    }
    return ret;//返回字符的UTF-8
}

讀取出字符數組

public synchronized int read(char cbuf[], int off, int len)  throws IOException {
    if (!connected) {
        throw new IOException("Pipe not connected");
    } else if (closedByReader) {
        throw new IOException("Pipe closed");
    } else if (writeSide != null && !writeSide.isAlive()
               && !closedByWriter && (in < 0)) {
        throw new IOException("Write end dead");
    }

    if ((off < 0) || (off > cbuf.length) || (len < 0) ||//下表有效性檢查
        ((off + len) > cbuf.length) || ((off + len) < 0)) {
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {
        return 0;
    }

    /* possibly wait on the first character */
    int c = read();//調用上個函數獲得數據
    if (c < 0) {//判定緩衝區是否爲空
        return -1;
    }
    cbuf[off] =  (char)c;//寫入數組
    int rlen = 1;//實際讀取出的長度
    while ((in >= 0) && (--len > 0)) {//循環讀取
        cbuf[off + rlen] = buffer[out++];
        rlen++;
        if (out >= buffer.length) {
            out = 0;
        }
        if (in == out) {
            /* now empty */
            in = -1;
        }
    }
    return rlen;
}

檢查當前管道是否可以進行數據讀取

public synchronized boolean ready() throws IOException {
    if (!connected) {
        throw new IOException("Pipe not connected");
    } else if (closedByReader) {
        throw new IOException("Pipe closed");
    } else if (writeSide != null && !writeSide.isAlive()
               && !closedByWriter && (in < 0)) {
        throw new IOException("Write end dead");
    }
    if (in < 0) {
        return false;
    } else {//管道有效且緩衝區不爲空
        return true;
    }
}

關閉當前管道

public void close()  throws IOException {
    in = -1;//清空緩衝區
    closedByReader = true;//reader端關閉
}


該類與PipedInputStream類基本一樣,只是在操作的時候加入char類型的強制轉碼,該類一些需要注意的地方與PipedInputStream相同,如有需要請查閱。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章