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的倍數,理論上速度提高1024倍

        int len = 0 ;
        while( (len = fis.read(by))!= -1 ){
            System.out.print(new String(by , 0 , 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的倍數,理論上速度提高1024倍

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

fis.close() ;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章