Java2 JDK5.0 教學手冊第三版洪維恩編著博碩文化出版書號 pg20210 第十四章檔案處理 本章學習目標認識串流學習檔案的開啟與關閉學習如何處理文字檔學習如何處理二進位檔
檔案處理 14-2 14.1 關於串流 串流可分為 輸入串流 (input stream) 與 輸出串流 (output stream) 兩種 下圖說明了串流如何做為檔案處理的橋樑 : stream 資料 input stream 0101011010110100 讀取由程式讀取 0100100100111... 程式執行結果 output stream 0101011010110100 寫入螢幕 0100100100111... // 檔案 I
檔案處理 14-3 下圖列出了與檔案相關類別的繼承圖 用來處理純文字檔 Reader BufferedReader java.lang.object InputStreamReader FileReader Writer BufferedWriter OutputStreamWriter FileWriter InputStream OutputStream FileInputStream FileOutputStream 用來處理純文字檔或二進位檔
檔案處理 14-4 14.2 檔案的基本處理 下面列出了 Reader 與 Writer 類別所提供的 method 表 14.2.1 Reader 類別的 method method void close() int read() int read(char[] cbuf) int read(char[] cbuf, int off, int len) long skip(long n) 關閉串流 讀取串流中的一個字元 從串流讀取資料, 放到字元陣列 cbuf 中, 並傳回所讀取字元的總數 從串流讀取資料, 並放到陣列 cbuf 的某個範圍 (off 表示陣列索引值,len 表示讀取字元數 ) 跳過 n 個字元不讀取
檔案處理 14-5 表 14.2.2 Writer 類別的 method method void close() abstract void flush() void write(char[] cbuf) void write(char[] cbuf, int off, int len) void write(int c) void write(string str) void write(string str, int off, int len) 關閉串流 將緩衝區的資料寫到檔案裡 注意這是抽象 method, 其明確的定義是撰寫在 Writer 的子類別裡 將字元陣列輸出到串流 將字元陣列依指定的格式輸出到串流中 (off 表示陣列索引值,len 表示寫入字元數 ) 將單一字元 c 輸出到串流中 將字串 str 輸出到串流中 將字串 str 輸出到串流 (off 表示陣列索引值,len 表示寫入字元數 )
檔案處理 14-6 14.2.1 讀取檔案的內容 -- 使用 FileReader 類別 FileReader 類別可用來讀取文字檔 FileReader() 建構元的格式可參考下表 : 表 14.2.3 FileReader 建構元 建構元 FileReader(String name) 依檔案名稱建立一個可供讀取字元的輸入串流物件
檔案處理 14-7 下面的範例說明了如何讀取文字檔 train.txt: 01 // app14_1, 使用 FileReader 類別讀取檔案 02 import java.io.*; // 載入 java.io 類別庫裡的所有類別 03 public class app14_1 04 { 05 public static void main(string args[]) throws IOException 06 { 07 char data[]=new char[128]; // 建立可容納 128 個字元的陣列 08 FileReader fr=new FileReader("c:\\Java\\train.txt"); // 建立物件 fr 09 10 int num=fr.read(data); // 將資料讀入字元串列 data 內 11 String str=new String(data,0,num); // 將字元串列轉換成字串 12 System.out.println("Characters read= "+num); 13 System.out.println(str); 14 15 fr.close(); 16 } 17 } /* app14_1 OUTPUT--- Characters read= 29 火車快飛, 火車快飛越過高山, 飛過小溪不知走了幾百里 -------------------*/
檔案處理 14-8 Java 把一個中文字看成是一個字元, 在 Windows 裡,Java 把換行字元 \r\n 看成是兩個字元, 如下圖所示 : 火車快飛, 火車快飛 \r \n 1 2 3 4 5 6 7 8 9 10 11 越過高山, 飛過小溪 \r \n 12 13 14 15 16 17 18 19 20 21 22 不知走了幾百里 23 24 25 26 27 28 29
檔案處理 14-9 14.2.2 將資料寫入檔案 -- 使用 FileWriter 類別 FileWriter 類別可用來將字元型態的資料寫入檔案 FileWriter() 建構元的格式可參考下表 : 表 14.2.4 FileWriter 建構元 建構元 FileWriter(String filename) FileWriter(String filename, Boolean a) 依檔案名稱建立一個可供寫入字元資料的串流物件, 原先的檔案會被覆蓋 同上, 但如果 a 設為 true, 則會將資料附加在原先的資料後面
檔案處理 14-10 下面的範例說明如何以 FileWriter 類別將字元陣列與字串寫到檔案裡 : 01 // app14_2, 使用 FileWriter 類別將資料寫入檔案內 02 import java.io.*; 03 public class app14_2 04 { 05 public static void main(string args[]) throws IOException 06 { 07 FileWriter fw=new FileWriter("c:\\Java\\proverb.txt"); 08 char data[]={'t','i','m','e',' ','f','l','i','e','s','!','\r','\n'}; 09 String str="end of file"; 10 fw.write(data); // 將字元陣列寫到檔案裡 11 fw.write(str); // 將字串寫到檔案裡 12 fw.close(); 13 } 14 } 用記事本開啟 proverb.txt, 將可看到如下的內容 :
檔案處理 14-11 14.3 利用緩衝區來讀寫資料 具有緩衝區的檔案處理方式是在存取時, 會先將資料放置到緩衝區 : 將資料寫入檔案裡 程式將資料寫入緩衝區 若緩衝區的資料裝滿, 或檔案關閉時, 則會將資料從緩衝區寫入磁碟中 程式 緩衝區 磁碟 程式直接從緩衝區讀取資料 如果緩衝區裡沒有資料, 則會從磁碟機裡讀取資料至緩衝區 從檔案讀取資料
檔案處理 14-12 14.3.1 從緩衝區讀取資料 -- 使用 BufferedReader 類別 下表列出了 BufferedReader 類別常用的建構元與 method: 表 14.3.1 BufferedReader 的建構元 建構元 BufferedReader(Reader in) BufferedReader(Reader in, int size) 建立緩衝區字元讀取串流 建立緩衝區字元讀取串流, 並設定緩衝區大小 表 14.3.2 method void close() int read() BufferedReader 的 method int read(char[] cbuf, int off, int len) long skip(long n) String readline() 關閉串流 讀取單一字元 讀取字元陣列 (off 表示陣列索引值,len 表示讀取位元數 ) 跳過 n 個字元不讀取 讀取一行字串
檔案處理 14-13 下面是以 BufferedReader 類別讀取 number.txt 的範例 : 01 // app14_3, 從緩衝區裡讀入資料 02 import java.io.*; 03 public class app14_3 04 { 05 public static void main(string args[]) throws IOException 06 { 07 String str; 08 int count=0; 09 FileReader fr=new FileReader("c:\\Java\\number.txt"); 10 BufferedReader bfr=new BufferedReader(fr); 11 12 while((str=bfr.readline())!=null) // 每次讀取一行, 直到檔案結束 13 { 14 count++; // 計算讀取的行數 15 System.out.println(str); 16 } 17 System.out.println(count+" lines read"); 18 19 fr.close(); // 關閉檔案 20 } 21 } /* app14_3 OUTPUT--- 12 34 63 14 16 56 6 lines read --------------------*/
檔案處理 14-14 14.3.2 將資料寫入緩衝區 -- 使用 BufferedWriter 類別 下表列出了 BufferedWriter 類別常用的建構元與 method: 表 14.3.3 BufferedWriter 的建構元 建構元 BufferedWriter(Writer out) BufferedWriter(Writer out, int size) 建立緩衝區字元寫入串流 建立緩衝區字元寫入串流, 並設定緩衝區的大小 表 14.3.4 method void close() void flush() void newline() void writer(int c) BufferedWriter 的 method void writer(char [ ] cbuf, int off, int len) 關閉串流 寫入緩衝區內的字元到檔案裡 寫入換行字元 寫入單一字元 寫入字元陣列 (off 表示陣列索引值,len 表示讀取位元數 ) void writer(string s, int off, int len) 寫入字串 (off 與 len 代表的意義同上 )
檔案處理 14-15 下面的範例說明了如何使用 BufferedWrite: 01 // app14_4, 將資料寫到緩衝區內 02 import java.io.*; 03 public class app14_4 04 { 05 public static void main(string args[]) throws IOException 06 { 07 FileWriter fw=new FileWriter("c:\\Java\\random.txt"); 08 BufferedWriter bfw=new BufferedWriter(fw); 09 10 for(int i=1;i<=5;i++) 11 { 12 bfw.write(double.tostring(math.random())); // 寫入亂數到緩衝區 13 bfw.newline(); // 寫入換行符號 14 } 15 bfw.flush(); // 將緩衝區內的資料寫到檔案裡 16 fw.close(); // 關閉檔案 17 } 18 }
如果打開 random.txt, 將可看到如下的類似畫面 : 檔案處理 14-16
檔案處理 14-17 14.4 使用 InputStream 與 OutputStream 類別 InputStream 與 OutputSteram 類別可以處理純文字檔及二進位檔 (binary file) 的資料 14.4.1 讀取檔案的內容 -- 使用 FileInputStream 類別 下表列出了 FileInputStream 類別的建構元與常用的 method: 表 14.4.1 FileInputStream 的建構元 建構元 FileInputStream (String name) 根據所給予的字串建立 FileInputStream 類別的物件
檔案處理 14-18 表 14.4.2 method int available() void close() long skip(long n) int read() int read(byte[] b) FileInputStream 類別的 method int read(byte[] b, int off, int len) 取得所讀取資料所佔的位元組數 (bytes) 關閉位元串流 在位元串流裡略過 n 個位元的資料 從輸出串流讀取一個位元組 從輸出串流讀取位元資料, 並它存放到陣列 b 中 從輸出串流讀取位元資料, 並存放到指定的陣列中 (off 表示陣列索引值,len 表示讀取位元數 )
檔案處理 14-19 下面的範例示範如何使用 FileInputStream 類別 : 01 // app14_5, 利用 FileInputStream 讀取檔案 02 import java.io.*; 03 public class app14_5 04 { 05 public static void main(string args[]) throws IOException 06 { 07 FileInputStream fi=new FileInputStream("c:\\Java\\train.txt"); 08 System.out.println("file size="+fi.available()); 09 byte ba[]=new byte[fi.available()]; // 建立 byte 陣列 10 11 fi.read(ba); // 將讀取的內容寫到陣列 ba 裡 12 System.out.println(new String(ba)); // 印出陣列 ba 的內容 13 fi.close(); 14 } 15 } /* app14_5 OUTPUT--- file size=54 火車快飛, 火車快飛越過高山, 飛過小溪不知走了幾百里 --------------------*/
檔案處理 14-20 14.4.2 將資料寫入檔案 -- 使用 FileOutputStraem 類別 下表列出了 FileOutputStream 類別的建構元與其常用的 method: 表 14.4.3 FileOutputStream 建構元 建構元 FileOutputStream(String filename) FileOutputStream(String name, Boolean a) 依檔案名稱建立一個可供寫入資料的輸出串流物件, 原先的檔案會被覆蓋 同上, 但如果 a 設為 true, 則會將資料附加在原先的資料後面 表 14.4.4 FileOutputStream 類別的方法 method void close() void write(byte[] b) void write(byte[] b, int off, int len) 關閉位元串流 寫入位元陣列 b 到串流裡 寫入位元陣列 b 到串流裡 (off 表示陣列索引值,len 表示寫入位元數 )
檔案處理 14-21 app14_6 示範了如何讀入一個 gif 圖檔, 並將它另存新檔 01 // app14_6, 讀入與寫入二進位檔案 02 import java.io.*; 03 public class app14_6 04 { 05 public static void main(string args[]) throws IOException 06 { 07 FileInputStream fi=new FileInputStream("c:\\Java\\lena.gif"); 08 FileOutputStream fo=new FileOutputStream("c:\\Java\\my_lena.gif"); 09 10 System.out.println("file size="+fi.available()); // 印出檔案大小 11 byte data[]=new byte[fi.available()]; // 建立 byte 型態的陣列 data 12 13 fi.read(data); // 將圖檔讀入 data 陣列 14 fo.write(data); // 將 data 陣列裡的資料寫入新檔 my_lena.gif 15 System.out.println("file copied and renamed"); 16 fi.close(); 17 fo.close(); 18 } 19 } /* app14_6 OUTPUT----- file size=72553 file copied and renamed -----------------------*/
檔案處理 14-22 從下面的畫面中, 可以確定檔案已正確的寫入, 且檔案大小也正確無誤 : 圖檔的大小為 72553 bytes
檔案處理 14-23