天天看點

JAVA學習筆記——IO流(位元組流)

1.IO流用來解決裝置間的資料傳輸問題。

2.IO流的分類

  按流的方向:

    輸入流:讀取資料

    輸出流:寫出資料

  按資料類型:

    位元組流

      位元組輸入流:讀取資料 InputStream

      位元組輸出流:寫出資料 OutputSteam

    字元流

      字元輸入流:讀取資料 Reader

      字元輸出流:寫出資料 Writer

  什麼情況下使用哪種流呢?

    如果資料所在的檔案通過Windows自帶的檔案夾可以打開并且能夠讀懂裡面的内容,就用字元流。其他用位元組流

    如果什麼都不知道,就用位元組流。

  注意:InputSteam和OutputSteam都是抽象類(abseract),不能直接用,需要使用它們具體的子類。

  其實作類主要有以下:

  InputStream:FileInputStream, FilterInputStream,StringBufferInputStream 等

  OutputStream: FileOutputStream, FilterOutputStream 等

  注意:每種基類的子類都是以父類名作為字尾名

  

3. 位元組輸出流FileOutputSteam

  構造函數:

    public void FileOutputStream(File file) :建立一個指向該file檔案的位元組輸出流對象

    public void FileOutputStream(String name) :建立一個指向該路徑的位元組輸出流對象

    public void FileOutputStream(File file, boolean append) :建立一個指向該file檔案的位元組輸出流對象,如果append值為true,則将位元組寫到檔案末尾處,否則會覆寫原來的。

    public void FileOutputStream(String name, boolean append) :建立一個指向該路徑的位元組輸出流對象,如果append值為true,則将位元組寫到檔案末尾處,否則會覆寫原來的。

  寫資料方法:

    public void write(byte[] b) :寫一個位元組

    public void write(int b) :寫一個位元組數組

    public void write(byte[] b, int off, int len) :寫一個位元組數組的一部分

  使用步驟:

    A:建立位元組輸出流對象

      FileOutputSteam fos = new FileOutputSteam(“fos.txt”) ;

       此處位元組輸出流做了幾件事情:

       1)如果不存在該檔案,則調用系統功能去建立該檔案,如果存在則不做這件事

       2)建立fos對象

       3)把fos指向這個檔案

       

    B:寫資料

      fos.write( “Hello.IO”.getBytes() ) ;

       此處用的方法是 void write(byte[] b) ; 可見參數是一個位元組數組,是以要把字元串轉換為位元組數組。

       

    C:釋放資源

      fos.close() ;

       為什麼一定要close()呢?

       1)讓流對象變成垃圾,這樣就可以被垃圾回收器回收

       2)通知系統去釋放跟該檔案相關的資源(這點很重要)

  

  問題1:如何在寫入的時候實作換行?

    很簡單,隻需要在寫入位元組流的時候同時寫入換行符即可。但是不同系統的換行符是不同的,

    Windows:\r\n

    Linux:\n

    Mac:\n

    而一些常見的進階記事本是可以識别任意換行符的。

  

  使用IO流的過程中需要注意的事會需要加入異常處理,是以上述代碼的最終完美版應該事下面這樣:

FileOutputStream fos = null ;   //這裡不指派為null的話close()方法會報錯
try{
    fos = new FileOutputStream("fos.txt") ;  //如果是絕對路徑,這裡可能會出現找不到路徑的情況,即FileNotFoundException異常
    fos.write("hello.IO".getBytes());  //這裡可能會報IOException的異常
}catch(FileNotFoundException e){   
    e.printStackTrace();
}catch (IOException e) {
    e.printStackTrace();
}finally{     //為了防止上面兩步出錯導緻位元組流無法運作close()方法,把關閉位元組流方法寫到finally中即可。
    if(fos != null)   //如果第一步找不到路徑的話fos就會為空,那麼對象調用close()方法就會無意義,是以為了防止這種情況,加入一個判斷
        try {
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
}
           

4、位元組輸入流FileInputStream

  構造方法

    public FileInputStream(File file) :

    public FileInputStream(String name) :

  讀取方法:

    int read():一次讀取一個位元組,讀到檔案結尾的話傳回-1

    int read(byte[] b):一次讀取一個位元組數組,傳回的結果是實際讀取到的資料的長度,讀到檔案結尾則傳回-1

  讀取步驟:

    A:建立位元組輸入流對象

      FileInputStream fis = new FileInputStream (“fis.txt”) ;

    B:調用read()方法讀取資料,并傳回該位元組對應的int值

      int b = fis.read() ;

    C:釋放資源

      fis.close() ;

    因為read()方法一次指讀取一個位元組,是以要用循環判斷來讀取。如下:

    int b = 0 ;

    while(int b = fis.read() != -1){

      System.out.print((char) b) ;

    }

    注意:這裡隻能讀取數字和英文字元,不能讀取中文漢字,因為漢子占用兩個位元組,這樣讀取到的漢子都是亂碼,是以才會出現字元流。

    在計算機中中文存儲用的兩個位元組,其中

      第一個位元組肯定是負數,

      第二個位元組常見的是負數,可能有負數,但是沒影響。

  但是,實際用中并不常用read()來進行單位元組讀取,通常是使用read(byte[] b)方法,這樣的效率會比單位元組讀取速度提升位元組數組的長度倍(理論上)。其最終版代碼如下:

FileInputStream fis = new FileInputStream("fis.txt") ;

        byte[] by = new byte] ;  //這裡的位元組數組長度通常設定為1024或者1024的倍數,理論上速度提高1024倍

        int len = ;
        while( (len = fis.read(by))!= ){
            System.out.print(new String(by , , len)); //這裡一定要用0-len的長度輸出,防止最後一次讀取隻能更新位元組數組的前面一部分。
        }

        fis.close() ;
           

    

5. 由上我們可以看到設定一個數組作為緩沖區确實可以提高讀寫效率

 既然這樣的的話,Java在開始設計的時候也采用的這樣的思想,提供了一種帶緩沖區的位元組類。這種類被稱為緩沖區類(高效類)。

 寫資料:BufferOutputStream

   構造方法:

     BufferOutputStream(OutputStream out) :建立一個緩沖輸出流,把資料寫入指定的底層輸出流

     BufferOutputStream(OutputStream out , int size):建立一個指定大小的緩沖輸出流,把資料寫入指定的底層輸出流

     注意:為什麼不直接指定具體的檔案或者路徑而是指定一個輸出流對象呢?

       因為字元緩沖流僅僅提供緩沖區,為高效設計的,但是真正的讀寫還是要靠基本的流對象來實作。

     

BufferOutputStream bos = new BufferOutputStream(new FileOutputStream("bos.txt")) ; //通常采用匿名對象方法

bos.write("hello".getBytes());

bos.close() ;
           

 讀資料:BufferInputStream

   構造方法:

     BufferInputStream(InputStream in) :建立一個緩沖輸入流

     BufferInputStream(InputStream in , int size):建立一個指定大小的緩沖輸入流

BufferInputStream bis= new BufferInputStream(new BufferInputStream("bis.txt")) ;

byte[] by = new byte] ;  //這裡的位元組數組長度通常設定為1024或者1024的倍數,理論上速度提高1024倍

int len = ;
while( (len = bis.read(by))!= ){
    System.out.print(new String(by , , len)); //這裡一定要用0-len的長度輸出,防止最後一次讀取隻能更新位元組數組的前面一部分。
}

fis.close() ;
           

繼續閱讀