1. 程式人生 > >Java進階(二)檔案讀操作

Java進階(二)檔案讀操作

               

本文以實際的讀取檔案為例子,介紹流的概念,以及輸入流的基本使用。

按照前面介紹的知識,將檔案中的資料讀入程式,是將程式外部的資料傳入程式中,應該使用輸入流——InputStreamReader。而由於讀取的是特定的資料來源——檔案,則可以使用輸入對應的子類FileInputStreamFileReader實現。

   在實際書寫程式碼時,需要首先熟悉讀取檔案在程式中實現的過程。在Java語言的IO程式設計中,讀取檔案是分兩個步驟:1、將檔案中的資料轉換為流,2、讀取流內部的資料。其中第一個步驟由系統完成,只需要建立對應的流物件即可,物件建立完成以後步驟1就完成了,第二個步驟使用輸入流物件中的read

方法即可實現了。

   使用輸入流進行程式設計時,程式碼一般分為3個部分:1、建立流物件,2、讀取流物件內部的資料,3、關閉流物件。下面以讀取檔案的程式碼示例:

 import java.io.*;

/**

 * 使用FileInputStream讀取檔案

 */

public class ReadFile1 {

         public static void main(String[] args) {

                   //宣告流物件

                   FileInputStream fis = null;                 

                   try{

                            //建立流物件

                            fis = new FileInputStream("e:\\a.txt");

                            //讀取資料,並將讀取到的資料儲存到陣列中

                            byte[] data = new byte[1024]; 

     //當前下標   

                            int i = 0; 

                            //讀取流中的第一個位元組資料

                            int n = fis.read();

                            //依次讀取後續的資料

//未到達流的末尾       

                            while(n != -1){

                                     //將有效資料儲存到陣列中

                                     data[i] = (byte)n;

                                     //下標增加

                                     i++;

                                     //讀取下一個位元組的資料

                                      n = fis.read();

                            }

                            //解析資料

                            String s = new String(data,0,i);

                            //輸出字串

                            System.out.println(s);

                   }catch(Exception e){

                            e.printStackTrace();

                   }finally{

                            try{

                                     //關閉流,釋放資源

                                     fis.close();

                            }catch(Exception e){}

                   }

         }

}

在該示例程式碼中,首先建立一個FileInputStream型別的物件fis

    fis = new FileInputStream("e:\\a.txt");

這樣建立了一個連線到資料來源e:\a.txt的流,並將該資料來源中的資料轉換為流物件fis,以後程式讀取資料來源中的資料,只需要從流物件fis中讀取即可。

讀取流fis中的資料,需要使用read方法,該方法是從InputStream類中繼承過來的方法,該方法的作用是每次讀取流中的一個位元組,如果需要讀取流中的所有資料,需要使用迴圈讀取,當到達流的末尾時,read方法的返回值是-1

在該示例中,首先讀取流中的第一個位元組:

     int n = fis.read();

    並將讀取的值賦值給intn,如果流fis為空,則n的值是-1,否則n中的最後一個位元組包含的時流fis中的第一個位元組,該位元組被讀取以後,將被從流fis中刪除。

然後迴圈讀取流中的其它資料,如果讀取到的資料不是-1,則將已經讀取到的資料n強制轉換為byte,即取n中的有效資料——最後一個位元組,並存儲到陣列data中,然後呼叫流物件fis中的read方法繼續讀取流中的下一個位元組的資料。一直這樣迴圈下去,直到讀取到的資料是-1,也就是讀取到流的末尾則迴圈結束。

 這裡的陣列長度是1024,所以要求流中的資料長度不能超過1024,所以該示例程式碼在這裡具有一定的侷限性。如果流的資料個數比較多,則可以將1024擴大到合適的個數即可。

經過上面的迴圈以後,就可以將流中的資料依次儲存到data陣列中,儲存到data陣列中有效資料的個數是i個,即迴圈次數。

其實截至到這裡,IO操作中的讀取資料已經完成,然後再按照資料來源中的資料格式,這裡是檔案的格式,解析讀取出的byte陣列即可。

該示例程式碼中的解析,只是將從流物件中讀取到的有效的資料,也就是data陣列中的前n個數據,轉換為字串,然後進行輸出。

在該示例程式碼中,只是在catch語句中輸出異常的資訊,便於程式碼的除錯,在實際的程式中,需要根據情況進行一定的邏輯處理,例如給出提示資訊等。

最後在finally語句塊中,關閉流物件fis,釋放流物件佔用的資源,關閉資料來源,實現流操作的結束工作。

上面詳細介紹了讀取檔案的過程,其實在實際讀取流資料時,還可以使用其它的read方法,下面的示例程式碼是使用另外一個read方法實現讀取的程式碼:

import java.io.FileInputStream;

/**

 * 使用FileInputStream讀取檔案

 */

public class ReadFile2 {

         public static void main(String[] args) {

                   //宣告流物件

                   FileInputStream fis = null;                 

                   try{

                            //建立流物件

                            fis = new FileInputStream("e:\\a.txt");

                            //讀取資料,並將讀取到的資料儲存到陣列中

                            byte[] data = new byte[1024]; //資料儲存的陣列

                            int i = fis.read(data);

                            //解析資料

                            String s = new String(data,0,i);

                            //輸出字串

                            System.out.println(s);

                   }catch(Exception e){

                            e.printStackTrace();

                   }finally{

                            try{

                                     //關閉流,釋放資源

                                     fis.close();

                            }catch(Exception e){}

                   }

         }

}

該示例程式碼中,只使用一行程式碼:

int i = fis.read(data);

就實現了將流物件fis中的資料讀取到位元組陣列data中。該行程式碼的作用是將fis流中的資料讀取出來,並依次儲存到陣列data中,返回值為實際讀取的有效資料的個數。

使用該中方式在進行讀取時,可以簡化讀取的程式碼。

當然,在讀取檔案時,也可以使用Reader類的子類FileReader進行實現,在編寫程式碼時,只需要將上面示例程式碼中的byte陣列替換成char陣列即可。

使用FileReader讀取檔案時,是按照char為單位進行讀取的,所以更適合於文字檔案的讀取,而對於二進位制檔案或自定義格式的檔案來說,還是使用FileInputStream進行讀取,方便對於讀取到的資料進行解析和操作。

讀取其它資料來源的操作和讀取檔案類似,最大的區別在於建立流物件時選擇的類不同,而流物件一旦建立,則基本的讀取方法是一樣,如果只使用最基本的read方法進行讀取,則使用基本上是一致的。這也是IO類設計的初衷,使得對於流物件的操作保持一致,簡化IO類使用的難度。