Java IO流:(七)節點流(文件流)之 FileInputStream


一、FileInputStream

  1、FileInputStream 類概述

    java.io.FileInputStream 類是文件輸入流,從文件中讀取數據,讀取到內存中使用。 

    FileInputStream 可用於字符文件或非字符文件的輸入,因為所有的文件都是由字節組成的。

  2、FileInputStream 類繼承結構

    

 

  3、構造方法

FileInputStream(File file) : 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的 File對象 file命名。
FileInputStream(String name) : 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的路徑名 name命名。

        參數:讀取文件的數據源

      String name:文件的路徑

      File file:文件對象

        構造方法的作用

      ① 會創建一個FileInputStream對象

      ② 會把FileInputStream對象指定構造方法中要讀取的文件

     讀取數據的原理(硬盤--> 內存)

      java程序-->JVM-->OS-->OS讀取數據的方法-->讀取文件

     字節輸入流的使用步驟重要】:

      ① 創建FileInputStream對象,構造方法中綁定要讀取的數據源

      ② 使用FileInputStream對象中的方法read,讀取文件

      ③ 釋放資源

 

二、常用方法

 

int read()

     從輸入流中讀取數據的下一個字節。 返回 到 255 范圍內的 int 字節值。 如果因為已經到達流末尾而沒有可用的字節, 則返回值 -1

int read(byte[] b)

    從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。 如果因為已經到達流末尾而沒有可用的字節, 則返回值 -1。 否則整數形式返回實際讀取的字節數

int read(byte[] b, int off,int len)

     將輸入流中最多 len 個數據字節讀入 byte 數組。 嘗試讀取 len 個字節, 但讀取的字節也可能小於該值。 以整數形式返回實際讀取的字節數。 如果因為流位於文件末尾而沒有可用的字節, 則返回值 -1

public void close() throws IOException

    關閉此輸入流並釋放與該流關聯的所有系統資源。

 

三、案例

  1、讀取文件的值

    代碼實現:

 1  @Test  2     public void testFileInputStream() {  3         FileInputStream fileInputStream = null;  4         try {  5             //1. 實例化File類的對象,指明要操作的文件
 6             File file = new File("hello.txt");  7 
 8             //2.提供具體的流
 9             fileInputStream = new FileInputStream(file); 10 
11             //3. 數據的讀入
12             int data = fileInputStream.read(); 13             while (data != -1) { 14                 System.out.print((char)data); 15                 data= fileInputStream.read(); 16  } 17         } catch (IOException e) { 18  e.printStackTrace(); 19         } finally { 20             //4. 流的關閉操作
21             try { 22                 if (fileInputStream != null) { 23  fileInputStream.close(); 24  } 25             } catch (IOException e) { 26  e.printStackTrace(); 27  } 28  } 29     }

 

    當文件中沒有中文的時候,運行結果如下:

    

     當文件中出現中文時:

    原文件:

    

    控制台輸出:

    

     這個時候竟然輸出亂碼了,為什么呢?(下面解釋)

  2、使用 read() 的重載方法讀取文件

    代碼實現:

 1  @Test  2     public void testFileInputStream1() {  3         FileInputStream fileInputStream = null;  4         try {  5             //1. 實例化File類的對象,指明要操作的文件
 6             File file = new File("hello.txt");  7 
 8             //2.提供具體的流
 9             fileInputStream = new FileInputStream(file); 10 
11             //3. 數據的讀入
12             byte[] buffer = new byte[5]; 13             int len;//記錄每次讀取的字節的個數
14             while((len = fileInputStream.read(buffer)) != -1){ 15                 String str = new String(buffer,0,len); 16  System.out.print(str); 17 
18  } 19         } catch (IOException e) { 20  e.printStackTrace(); 21         } finally { 22             //4. 流的關閉操作
23             try { 24                 if (fileInputStream != null) { 25  fileInputStream.close(); 26  } 27             } catch (IOException e) { 28  e.printStackTrace(); 29  } 30  } 31     }

 

    當讀取的文件中沒有中文時,也是正常的。

    

     可是當文件中有中文時:

    

     這個時候又出現亂碼了!!!

 

  3、為什么會出現亂碼呢?

      這是因為英文和中文的字符集不同的原因。

      英文情況下,無論是 ASCII編碼還是 UTF-8編碼,一個字母都會占一個字節。

      中文情況下,使用的 UTF-8 編碼,這個文字就會占用 三個字節。

      (1)情況一:使用 read() 一個個讀取

          ① 當讀取英文時:

          

 

           會一個個字節去讀,而一個英文正好對應一個字節。

          ② 當包含中文時:

          

 

           由於里面包含中文,一個中文占用三個字節,一個個字節去讀取的時候,會把一個中文拆分為三個字節,依次顯示出來,就呈現這樣的效果。

      (2)情況二:使用 read(Char[] cbuf) 讀取

        ① 當讀取英文時:

          

           使用字節數組讀取時,英文也正好可以讀取顯示。

        ② 當讀取中文時:

        

         使用字節數組讀取時,會把中文拆分讀取,然后進行顯示。

        最后運行結果:

        

 

  4、使用字節數組讀取

    read(byte[] b) ,每次讀取b的長度個字節到數組中,返回讀取到的有效字節個數,讀取到末尾時,返回 -1 。

    int read(byte[] b) 從輸入流中讀取一定數量的字節,並將其存儲在緩沖區數組 b 中。

    明確兩件事情:

      a. 方法的參數byte[]的作用?

        起到緩沖作用,存儲每次讀取到的多個字節,數組的長度一把定義為1024(1kb)或者1024的整數倍

      b.方法的返回值int是什么?

        每次讀取的有效字節個數

    Demo:

 1  public static void main(String[] args) throws IOException { 2         //創建FileInputStream對象,構造方法中綁定要讀取的數據源
 3         FileInputStream fis = new FileInputStream("E:\\b.txt"); 4         //使用FileInputStream對象中的方法read讀取文件
 5         //int read(byte[] b) 從輸入流中讀取一定數量的字節,並將其存儲在緩沖區數組 b 中。
 6          /* 7 發現以上讀取時一個重復的過程,可以使用循環優化 8 不知道文件中有多少字節,所以使用while循環 9 while循環結束的條件,讀取到-1結束 10 */
11         byte[] bytes = new byte[1024];//存儲讀取到的多個字節
12         int len = 0; //記錄每次讀取的有效字節個數
13         while((len = fis.read(bytes))!=-1){ 14             //String(byte[] bytes, int offset, int length) 把字節數組的一部分轉換為字符串 offset:數組的開始索引 length:轉換的字節個數
15             System.out.println(new String(bytes,0,len)); 16 } 17 
18         //釋放資源
19 fis.close(); 20     }

 

     Tips:使用數組讀取,每次讀取多個字節,減少了系統間的IO操作次數,從而提高了讀寫的效率,建議開發中使用。

    字節流讀取文件的原理:

  

 

四、復制文件

  復制文件原理圖解:

  文件復制的步驟

    1. 創建一個字節輸入流對象,構造方法中綁定要讀取的數據源

    2. 創建一個字節輸出流對象,構造方法中綁定要寫入的目的地

    3. 使用字節輸入流對象中的方法read讀取文件

    4. 使用字節輸出流中的方法write,把讀取到的字節寫入到目的地的文件中

    5. 釋放資源;

  代碼實現

 1 public static void main(String[] args) throws IOException { 2         //1.創建一個字節輸入流對象,構造方法中綁定要讀取的數據源
 3         FileInputStream fis = new FileInputStream("c:\\1.jpg"); 4         //2.創建一個字節輸出流對象,構造方法中綁定要寫入的目的地
 5         FileOutputStream fos = new FileOutputStream("d:\\1.jpg"); 6         //一次讀取一個字節寫入一個字節的方式
 7         //3.使用字節輸入流對象中的方法read讀取文件
 8         /*int len = 0; 9 while((len = fis.read())!=-1){ 10 //4.使用字節輸出流中的方法write,把讀取到的字節寫入到目的地的文件中 11 fos.write(len); 12 }*/
13 
14         //使用數組緩沖讀取多個字節,寫入多個字節
15         byte[] bytes = new byte[1024]; 16         //3.使用字節輸入流對象中的方法read讀取文件
17         int len = 0;//每次讀取的有效字節個數
18         while((len = fis.read(bytes))!=-1){ 19             //4.使用字節輸出流中的方法write,把讀取到的字節寫入到目的地的文件中
20             fos.write(bytes,0,len); 21 } 22 
23         //5.釋放資源(先關寫的,后關閉讀的;如果寫完了,肯定讀取完畢了)
24 fos.close(); 25 fis.close(); 26     }

 

  注意:流的關閉原則,先開后關,后開先關。 

 

五、注意點

  1、對於文本文件(.txt,.java,.c,.cpp),使用字符流處理。

  2、對於非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字節流處理。

  3、使用字節流FileInputStream處理文本文件,可能出現亂碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM