最近打算把Java網絡編程相關的知識深刻一下(IO、NIO、Socket編程、Netty)java
Java的I/O創建於流之上。輸入流讀取數據、輸出流寫入數據編程
輸入流InputStream的API以下:網絡
public abstract int read() throws IOException;//-1 到 255 public int read(byte b[]) throws IOException public int read(byte b[], int off, int len) throws IOException public long skip(long n) throws IOException public int available() throws IOException public void close() throws IOException
read()方法返回的其實是一個無符號byte(Java中沒有無符號byte類型, 就直接用int做爲返回值了)性能
read方法返回-1時表明已經讀完數據(若是是網絡通訊的話就表明對端不會再發送數據)編碼
輸出流OutputStreamAPI以下:加密
// OutputStream接口定義的幾個方法 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
write(int) 方法實際寫入的是int的低8位(一個字節)code
儘可能不要使用write(int), 由於每次發送一個字節效率不高(每一個TCP報文都至少有40個字節的網絡傳輸開銷, 每次傳輸數據太少的話信道利用率不高)對象
flush() 將緩衝區中的內容刷到底層輸出流blog
流對應了底層的文件句柄和端口, 因此使用完成以後必定要關閉接口
下面是常見的一種關閉流的寫法(把流的關閉放在finally語句塊中),可是可太複雜了!!!
FileInputStream in = null; try { in = new FileInputStream("/tmp/axt.t"); // } catch (FileNotFoundException e) { // } finally { if (in != null){ try { in.close(); } catch (IOException e) { // } } }
簡潔一些的寫法
try(FileInputStream in = new FileInputStream("/tmp/a.txt")){ // do somethind } catch (Exception e) { // }
由於Java會對try塊中申明的全部AutoCloseable類型的對象自動調用close()方法,不須要手動調用!
過濾器流其實是對流功能的加強,使用的是裝飾模式。
裝飾模式就是在原有的基礎上增長了一些新的功能,經過組合實現。
下爲過濾器流類結構--裝飾模式的體現
下面這段代碼對FileInputStream 使用了 BufferedInputStream 和 DataInputStream 進行包裹
使得用戶能夠直接讀取字符, 且是從Java緩衝區中獲取(若是緩衝中沒有可用數據,再嘗試從底層輸入流讀取)
FileInputStream in = new FileOutputStream("/tmp/a.txt"); in = new BufferedInputStream(in); in = new DataInputStream(in); in.readChar();
過濾器流還能夠實現解壓(ZIPInputStream)、Base64解碼(Base64InputStream)等,也能夠自定義過濾器流以實現特定功能)
緩衝流做爲過濾器流中的一種, 在網絡通訊場景下使用緩衝有利於提高發送和接受數據的效率。
因此在發送數據時咱們應該使用BufferedOutputStream, 這樣寫數據時會先寫入到java的緩衝區中, 緩衝區滿或者調用flush方法時纔會真正的發送數據,可以提高性能(提高信道利用率)
OutputStream out = new FileOutputStream("/tmp/a.txt"); BufferedOutputStream outputStream = new BufferedOutputStream(out); out.write(1); out.flush();
緩衝流做爲過濾器流中的一種,提供直接讀寫Java基本類型的API
OutputStream out = new FileOutputStream("/tmp/a.txt"); DataOutputStream dataOutputStream = new DataOutputStream(out); dataOutputStream.writeChar('c'); //寫字符 dataOutputStream.writeUTF("ssss"); //寫字符串
提供讀寫字符的API(若是隻是ASCII編碼, 直接使用字節流便可)
OutputStreamWriter 提供直接讀取字符和字符串的能力
OutputStream out = new FileOutputStream("/tmp/a.txt"); //底層字節流 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); writer.write("哈哈哈");
BufferedWriter 提供一層寫緩衝(做用類同字節流的BufferedOutputStream)
OutputStream out = new FileOutputStream("/tmp/a.txt"); //底層字節流 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);//書寫器(編碼) writer = new BufferedWriter(writer, 1000);//緩衝書寫器 for (int i = 0; i < 128; i ++){ writer.write(i); } writer.write("哈哈哈哈哈");//寫漢字, utf-8編碼可見,若是是ascii編碼會亂碼 writer.flush(); //這裏其實不用flush, close以前會flush,可是最好有。 writer.close(); //close流, 釋放底層資源。
整體分紅兩類 字節流 和字符流, 字符流是僅對字節流的裝飾(或者說字符流的底層就是字節流)
過濾器流:對基礎流增長一些額外的功能 若是緩衝、壓縮、加密等
緩衝流:讀寫數據中間加一層緩衝區,提高數據傳輸效率。