Java面試官:開發過程中
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); } public long skip(long n) throws IOException { return in.skip(n); } public int available() throws IOException { return in.available(); } public void close() throws IOException { in.close(); } public synchronized void mark(int readlimit) { in.mark(readlimit); } public synchronized void reset() throws IOException { in.reset(); } public boolean markSupported() { return in.markSupported(); }
}
所以正如其名,FilterInputStream 就像是內部 InputStream 物件的一個過濾器一般,所有方法呼叫都需要經過一層包裝方法的『過濾』才能到達內部物件。FilterInputStream 並沒有邏輯實現,具體實現需要子類覆寫相關方法實現。 比較有意思的實現有以下幾個: * **BufferedInputStream** > BufferedInputStream 內部使用一個 buf 位元組陣列進行緩衝,覆寫了 FilterInputStream 的全部方法實現一個帶緩衝區的位元組流類。在進行磁碟或網路IO時,原始的InputStream對資料讀取的過程都是一個位元組一個位元組操作的,而BufferedInputStream在其內部提供了一個buffer,在讀資料時,會一次讀取一大塊資料到buffer中,這樣比單位元組的操作效率要高的多,特別是程序磁碟IO和對大量資料進行讀寫的時候,能提升IO效能。 * **PushbackInputStream** > PushbackInputStream 內部同樣使用一個 buf 位元組陣列對已讀資料進行快取,然後可以通過 unread 方法將已讀的資料重新放回 buf 陣列,從而實現了一個支援 push back 的位元組流類。 * **DataInputStream** > DataInputStream 提供了許多可以讀取 Java 基本型別的方法。 #### ByteArrayInputStream ByteArrayInputStream 支援從 byte 陣列讀取資料,通過建構函式可以指定該 byte 陣列:
protected byte buf[]; protected int pos; protected int mark = 0; protected int count; public ByteArrayInputStream(byte buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } public ByteArrayInputStream(byte buf[], int offset, int length) { this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); this.mark = offset; }
#### ObjectInputStream
ObjectInputStream 與 DataInputStream 類似也支援 Java 基本型別的讀取,此外還支援反序列化讀取物件。它常常與 ObjectOutputStream 搭配使用。因此,ObjectOutputStream 實現將基本型別或者物件序列化並輸出到 IO 位元組流或者裝置上,而 ObjectInputStream 從 IO 位元組流或者裝置上反序列化讀取基本型別或者物件。
比如,從檔案中讀取一個 person 物件。
ObjectInputStream input = new ObjectInputStream(new FileInputStream("data.txt"));
Person person = (MyClass) input.readObject();
input.close();
這裡要求 Person 一定要實現 java.io.Serializable 介面。
#### PipedInputStream
PipedInputStream 通常和 PipedOutputStream 搭配使用,實現了一個承載位元組流的管道類。PipedOutputStream 的輸出會自動呼叫 PipedInputStream 的 receive 方法作為輸入。PipedInputStream 提供了以下幾個特殊方法:
// 連線 PipedOutputStream 物件,形成管道
public void connect(PipedOutputStream src) throws IOException;
// 接收一個位元組
protected synchronized void receive(int b) throws IOException;
// 接收一個位元組陣列
synchronized void receive(byte b[], int off, int len) throws IOException;
注意到其 read 方法和 receive 都是同步方法,read 方法在沒有資料的時候會發生阻塞,而 receive 方法在緩衝陣列沒有剩餘空間的時候也會發生阻塞:
public synchronized int read() 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");
}
readSide = Thread.currentThread();
int trials = 2;
while (in < 0) {
// 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++] & 0xFF;
if (out >= buffer.length) {
out = 0;
}
if (in == out) {
/* now empty */
in = -1;
}
return ret;
}
protected synchronized void receive(int b) throws IOException {
checkStateForReceive();
writeSide = Thread.currentThread();
if (in == out)
// 當in等於out,意味著緩衝陣列已滿,阻塞等待空間釋放
awaitSpace();
if (in < 0) {
in = 0;
out = 0;
}
buffer[in++] = (byte)(b & 0xFF);
if (in >= buffer.length) {
in = 0;
}
}
#### SequenceInputStream
SequenceInputStream 支援將多個 InputStream 組合起來,並按照順序進行讀取。
### OutputStream
OutputStream 與 InputStream 相對應,實現上存在很多相似之處。先看看內部方法:
public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException {//}
public void write(byte b[], int off, int len) throws IOException {//}
public void flush() throws IOException {//}
public void close() throws IOException {//}
}
OutputStream 實現了 Closeable 介面和 Flushable 方法,同樣有一個抽象的 write 方法需要實現。其他方法提供框架性程式碼,也需要實現類覆寫相關方法,提供更多的自定義功能。
#### FileOutputStream
實現上與 FileInputStream 類似,提供對檔案寫入位元組流的功能。
#### FilterOutputStream
與 FilterInputStream 類似,對 OutputStream 物件進行包裝,並繼承了 OutputStream 並覆寫全部方法,方法內容都是簡單地呼叫內部的 OutputStream 物件。
同樣的也有幾個子類實現:
* **BufferedOutputStream**:帶緩衝區的位元組流輸出類,與 BufferedInputStream 對應;
* **DataOutputStream**:提供寫 Java 基本型別相關方法的位元組流類,與 DataInputStream 對應;
* **PrintStream**:與 DataOutputStream 有些類似,不過它提供了更加豐富的寫出方法,並且支援換行輸出。
#### ByteArrayOutputStream
與 ByteArrayInputStream 相反,ByteArrayOutputStream 實現輸出到內部的快取位元組陣列 buf 中。特有的方法有:
/** 將該 Stream 輸出為 byte 陣列/
public synchronized byte toByteArray()[] {
return Arrays.copyOf(buf, count);
}
/ 將該 Stream 輸出到另一個 Stream 上**/
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
#### ObjectOutputStream
與 ObjectInputStream 對應,ObjectOutputStream 實現將 Java 基本型別資料或者 Java 物件序列化後寫入輸出位元組流中。
#### PipedOutputStream
與 PipedInputStream 搭配使用,PipedOutputStream 會輸出位元組流到管道另一端的 PipedInputStream。
## 字元流
位元組流處理的是 byte 陣列,而字元流處理的是 char 陣列。而且字元流相關的類都以 Reader 或者 Writer 為字尾。
### Reader
先看看內部方法:
public abstract class Reader implements Readable, Closeable {
public int read(java.nio.CharBuffer target) throws IOException;
public int read() throws IOException;
public int read(char cbuf[]) throws IOException;
abstract public int read(char cbuf[], int off, int len) throws IOException;
public long skip(long n) throws IOException;
public boolean ready() throws IOException;
public boolean markSupported();
public void mark(int readAheadLimit) throws IOException;
public void reset() throws IOException;
abstract public void close() throws IOException;
}
內部方法與 InputStream 非常相似,同樣實現類需要實現 read 方法。
#### BufferedReader
帶緩衝區的 Reader 實現。
#### CharArrayReader
從字元陣列讀取資料的 Reader 實現。
#### InputStreamReader
InputStreamReader 是一個包裝類,內部物件是 StreamDecoder。StreamDecoder 支援從 InputStream 中讀取字元。
public class InputStreamReader extends Reader {
private final StreamDecoder sd;
/**
* Creates an InputStreamReader that uses the default charset.
*
* @param in An InputStream
*/
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
最後
做任何事情都要用心,要非常關注細節。看起來不起眼的、繁瑣的工作做透了會有意想不到的價值。
當然要想成為一個技術大牛也需要一定的思想格局,思想決定未來你要往哪個方向去走, 建議多看一些人生規劃方面的書籍,多學習名人的思想格局,未來你的路會走的更遠。
更多的技術點思維導圖我已經做了一個整理,涵蓋了當下網際網路最流行99%的技術點,在這裡我將這份導圖分享出來,以及為金九銀十準備的一整套面試體系,上到集合,下到分散式微服務
如何獲得這套優質的資料呢?