該類無引入包
繼承自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相同,如有需要請查閱。