1. 程式人生 > >節點流(檔案流)

節點流(檔案流)

# 節點流 ## FileReader和FileWriter 字元流(cha[]陣列) ### FileReader讀入資料的基本操作 #### 過程 1. 例項化File類的物件,指明要操作的檔案 注意: * 在@Test測試中的相對路徑是相對於當前Module * 在main函式的相對路徑是相對於當前工程 2. 提供具體的流 3. 資料的讀入過程 4. 流的關閉操作 5. try-catch-finally異常處理 #### 說明 * 一定要注意最後流的關閉 * read()的理解:返回讀入的一個字元。如果達到檔案末尾,返回-1 * 異常的處理:為了保證流資源一定可以執行關閉的操作,需要使用try-catch-finally來處理 * 讀入的檔案(hello.txt)一定要存在,否則會報FileNotFoundException異常 #### 程式碼實現 ```java @org.junit.Test public void test1(){ FileReader fileReader = null; try { //1. 例項化File類的物件,指明要操作的檔案 //注意:在@Test測試中的相對路徑是相對於當前Module,在main函式的相對路徑是相對於當前工程 File file = new File("hello.txt");//相對路徑 //2. 提供具體的流 fileReader = new FileReader(file); //3. 資料的讀入過程 //read():返回讀入的一個字元。如果達到檔案末尾,返回-1 //方式一 // int data = fileReader.read(); // while(data != -1){ // System.out.print((char)data); // data = fileReader.read(); // } //方式二:語法上針對方式一的修改 int data; while((data = fileReader.read()) != -1){ System.out.println((char)data); } } catch (IOException e) { e.printStackTrace(); }finally { //4. 流的關閉操作 try { //防止最開始提供流是出現異常導致這裡是空指標,所以加一個判斷 if(fileReader != null){ fileReader.close(); } } catch (IOException e) { e.printStackTrace(); } } } ``` #### 執行結果 此時的"hello.txt"文件中儲存的內容是hello ![o6Ij4.png](https://wx1.sbimg.cn/2020/08/06/o6Ij4.png) #### 使用read()的過載方法 * read():返回讀入的一個字元。如果達到檔案末尾,返回-1 * read(char[] cbuf):返回每次讀入cbuf陣列中的字元的個數。如果達到檔案末尾,返回-1(常用) * read(char cbuf[], int off, int len) (不常用) ##### read(char[] cbuf)的用法 1. 建立一個char的陣列cbuf (舉例假定該陣列的長度為5) >char[] cbuf = new char[5]; 2. 建立len變數,儲存read(char[] cbuf)的返回值 (注意:返回值即為每次讀入cbuf陣列中的字元的個數) 3. 讀取資料 * 寫法一:迴圈遍歷 ```java for (int i = 0; i < len; i++) { System.out.print(cbuf[i]); } ``` * 寫法二:char[]型別和String型別轉換 ```java String str = new String(cbuf,0,len); System.out.print(str); ``` https://www.cnblogs.com/CrabDumplings/p/13341279.html ![o91I2.png](https://wx1.sbimg.cn/2020/08/06/o91I2.png) 4. 流的關閉操作(不要忘記) ##### read(char[] cbuf)讀取資料時的注意事項 * 寫法一 ```java for (int i = 0; i < len; i++) { System.out.print(cbuf[i]); } ``` 其中for迴圈時,i一定要小於len(每次讀入cbuf陣列中的字元的個數)而不是cbuf.length * 畫圖說明: ![o9xOe.png](https://wx1.sbimg.cn/2020/08/06/o9xOe.png) 最後還剩下3個數據的時候: * 如果for迴圈中的i小於cbuf.length(錯誤的寫法) ![o9rpk.png](https://wx1.sbimg.cn/2020/08/06/o9rpk.png) 最後的輸出為:helloWorld123ld (其中hello為第一次的結果,World為第二次的結果,123ld為第三次的結果) 而檔案中的內容為helloWorld123,所以此時的寫法是錯誤的 * 如果for迴圈中的i小於len(正確的寫法) ![o9Ogn.png](https://wx2.sbimg.cn/2020/08/06/o9Ogn.png) 最後的輸出為:helloWorld123 (其中hello為第一次的結果,World為第二次的結果,123為第三次的結果) * 寫法二 ```java String str = new String(cbuf,0,len); System.out.print(str); ``` 其中利用了String(char[] value, int offset, int count)構造器,而不是String(char[] value)構造器 * String(char[] value)構造器(錯誤的寫法) 錯誤原因與寫法一錯誤的方法相同 * String(char[] value, int offset, int count)構造器(正確的寫法) 讀取char[]陣列中角標0到角標len的內容,過程與寫法一正確的方法過程類似 ### FileReader寫出資料的基本操作 #### 過程 1. 例項化File類的物件,指明要操作的檔案 2. 提供具體的流 3. 資料的寫出過程 4. 流的關閉操作 5. try-catch-finally異常處理 #### 說明 寫出操作,對應的File可以不存在。 * 如果不存在,在寫出的過程中,會自動建立此檔案 * 如果存在這個檔案 * 對原有檔案的覆蓋 流使用的構造器為 >FileWriter(file, false) 或者是 >FileWriter(file) * 在原有檔案的基礎上追加內容(不會對原有檔案進行覆蓋) 流使用的構造器為 >FileWriter(file, true) ![o9TfM.png](https://wx2.sbimg.cn/2020/08/06/o9TfM.png) #### 程式碼實現 ```java FileWriter fw1 = null; FileWriter fw2 = null; try { //1. 提供File類的物件,指明寫出到的檔案 File file = new File("hi.txt"); //2. 提供FileWriter的物件,用於檔案的寫出 //覆蓋 fw1 = new FileWriter(file,false); //不覆蓋 fw2 = new FileWriter(file,true); //3. 寫出的操作 fw1.write("I have a dream!\n"); fw2.write("123\n"); } catch (IOException e) { e.printStackTrace(); }finally { //4. 關閉流資源 if(fw1 != null) try { fw1.close(); } catch (IOException e) { e.printStackTrace(); }finally { if(fw2 != null) try { fw2.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 執行結果 最開始hi.txt檔案中的內容為hello 執行程式碼後 ![o9VQa.png](https://wx1.sbimg.cn/2020/08/06/o9VQa.png) ### 使用FileWriter和FileReader實現文字檔案的複製 #### 過程 1. 建立File類的物件,指明讀入和寫出的檔案 2. 建立輸入流和輸出流的物件 3. 資料的讀入和寫入操作 4. 關閉流資源 5. try-catch-finally異常處理 #### 說明 * 在讀取檔案檔案時,選擇read(char[] cbuf)的用法 * 在寫入檔案的時候,注意不要寫成 >
fw.write(cbuf); 此時出現的錯誤和讀取操作時寫法一會出現的錯誤相同,不可以正確的讀取檔案中原本的內容 需要使用 >fw.write(cbuf,0,len); 讀取cbuf陣列中角標為0的元素到角標為len的元素 * 在最後關閉流資源的時候,一定要注意兩個流都要關閉,即使其中一個流在關閉的時候丟擲異常另一個流也要關閉 有兩種寫法 * 寫法一 ```java finally { //4. 關閉流資源 if(fr != null) try { fr.close(); } catch (IOException e) { e.printStackTrace(); }finally { if(fw != null) try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` * 寫法二 ```java finally { //4. 關閉流資源 try { if(fr != null) fr.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fw != null) fw.close(); } catch (IOException e) { e.printStackTrace(); } } ``` #### 程式碼實現 ```java public void test4(){ FileReader fr = null; FileWriter fw = null; try { //1. 建立File類的物件,指明讀入和寫出的檔案 File file1 = new File("hello.txt"); File file2 = new File("hi.txt"); //2. 建立輸入流和輸出流的物件 fr = new FileReader(file1); fw = new FileWriter(file2,true); //3. 資料的讀入和寫入操作 char[] cbuf = new char[5]; int len;//記錄每次讀入到cbuf陣列中字元的個數 while((len = fr.read(cbuf)) != -1){ //每次寫出len個字元 fw.write(cbuf,0,len); } } catch (IOException e) { e.printStackTrace(); }finally { //4. 關閉流資源 try { if(fr != null) fr.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fw != null) fw.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 執行結果 ![oG51G.png](https://wx1.sbimg.cn/2020/08/06/oG51G.png) #### 注意 字元流不能處理圖片檔案等位元組資料!!! ## FileInputStream和FileOutputStream 位元組流(byte[]) ### 使用FileInputStream和FileOutputStream實現文字檔案的複製 #### 過程 1. 建立File類的物件,指明讀入和寫出的檔案 2. 建立輸入流和輸出流的物件 3. 資料的讀入和寫入操作 4. 關閉流資源 5. try-catch-finally異常處理 #### 程式碼實現 ```java FileInputStream fis = null; FileOutputStream fos = null; try { File srcfile = new File("殷志源.png"); File destfile = new File("丸子.png"); fis = new FileInputStream(srcfile); fos = new FileOutputStream(destfile); byte[] buffer = new byte[5]; int len; while((len = fis.read(buffer)) != -1){ fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(fis != null) fis.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } ``` #### 執行結果 ![oRznG.png](https://wx1.sbimg.cn/2020/08/07/oRznG.png) ![oRHMT.png](https://wx2.sbimg.cn/2020/08/07/oRHMT.png) ### 指定路徑下檔案的複製的方法 複製視訊 ```java public void copyFile(String srcPath, String destPath){ FileInputStream fis = null; FileOutputStream fos = null; try { File srcfile = new File(srcPath); File destfile = new File(destPath); fis = new FileInputStream(srcfile); fos = new FileOutputStream(destfile); byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(fis != null) fis.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` [![ocIS1.png](https://wx1.sbimg.cn/2020/08/07/ocIS1.png)](https://sbimg.cn/image/ocIS1) [![od4o2.png](https://wx1.sbimg.cn/2020/08/07/od4o2.png)](https://sbimg.cn/image/od4o2) ## 位元組流和字元流使用的注意事項 * 對於文字檔案(.txt, .java, .c, .cpp......),使用字元流來處理 * 對於非文字檔案(.jpg, .mp3, .mp4, .avi, .doc, .ppt......),使用位元組流來處理 * 如果只是想複製文字檔案,也可以使用位元組流(流在此時只是個搬運的作用) * 非文字只可以用位元組