Java I/O流

最近打算把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)

Demo

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流, 釋放底層資源。

總結

整體分紅兩類 字節流 和字符流, 字符流是僅對字節流的裝飾(或者說字符流的底層就是字節流)

過濾器流:對基礎流增長一些額外的功能 若是緩衝、壓縮、加密等

緩衝流:讀寫數據中間加一層緩衝區,提高數據傳輸效率。

相關文章
相關標籤/搜索