在上一節中,我們使用FileInputStream類和FileOutputStream類來實現了一個可以自由拷貝檔案的功能。為了提高效率,我們人為地定義一個緩衝區byte[] 數組。其實,我們可以使用BufferedInputStream類和BufferedOutputStream類來重寫這個功能。
5、BufferedInputStream、BufferedOutputStream
看到Buffererd這個詞,我們或許可以猜到,這兩個類應該是帶有緩衝區的流類。正如我們所想的那樣,它們確實有一個buf資料成員,是一個字元數組,預設大小為2048位元組。當我們在讀取資料時,BufferedInputStream會盡量將buf填滿;使用read()方法讀取資料時,實際上是先從buf中讀取資料,而不是直接從資料來源(如硬碟)上讀取。只有當buf中的資料不足時,BufferedInputStream才會調用InputStream的read()方法從指定資料來源中讀取。
BufferedOutputStream的資料成員buf是一個512位元組的位元組數組,當我們調用write()方法寫入資料時,實際上是先向buf中寫入,當buf滿後才會將資料寫入至指定裝置(如硬碟)。我們也可以手動地調用flush()函數來重新整理緩衝區,強制將資料從記憶體中寫出。
下面用這兩個類實現檔案複製功能:
package cls;import java.io.*;public class BufferedStreamDemo{ public static void main(String[] args) throws Exception { // 從命令列參數中指定檔案 File fSource = new File(args[0]); File fDest = new File(args[1]); // 建立帶緩衝的流對象 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fSource)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fDest)); // 提示資訊 System.out.println("copy " + fSource.length() + "bytes"); byte[] buf = new byte[1]; while(bis.read(buf) != -1) // read()返回int類型,返回-1表示已到檔案結尾 bos.write(buf); // 寫入資料 // 重新整理緩衝區 bos.flush(); // 關閉流 bos.close(); bis.close(); // 提示資訊 System.out.println("copy " + fDest.length() + "bytes finished"); }}
6、DataInputStream和DataOutputStream
DataInputStream和DataOutputStream類提供了對Java基礎資料型別 (Elementary Data Type)寫入的方法,如int,double,boolean。因為Java中基礎資料型別 (Elementary Data Type)的大小是固定的,不會因為不同的機器而改變,因此在寫入的時候就不必擔心不同平台資料大小不同的問題。
有一個writeUTF()方法值得我們注意。這個方法會將指定的String對象中的字元寫入,但在寫入的資料之前會首先寫入2個位元組的長度資料,這個資料指示了帶寫入的字元的大小。這樣的好處是當我們在使用readUTF()讀取資料的時候就不必考慮資料大小的問題了,直接讀取就行,因為在readUTF()內部會控制好讀取資料的長度。
package cls;import java.io.*;class Student{ String name; int score; // 構造方法 public Student(String name,int score) { this.name = name; this.score = score; } // 返回名字 public String getName() { return name; } // 返回分數 public int getScore() { return score; }}public class DataStreamDemo{ public static void main(String[] args) throws Exception { // 建立3個Student對象 Student[] sd = new Student[]{new Student("dog",100),new Student("pig",200),new Student("cat",300)}; // 建立輸出資料流對象 DataOutputStream dos = new DataOutputStream(new FileOutputStream(args[0])); //向檔案中寫入 // 使用增強for迴圈寫入資料 for(Student st : sd) { dos.writeUTF(st.getName()); // 寫入String dos.writeInt(st.getScore()); } dos.flush(); // 重新整理緩衝區 dos.close(); // 關閉流 // 從檔案中讀入資料 DataInputStream dis = new DataInputStream(new FileInputStream(args[0])); for(int i = 0 ; i < 3 ; ++i) { System.out.println(dis.readUTF()); // 取入String字串,不必擔心長度的問題 System.out.println(dis.readInt()); } dis.close(); }}