JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤...

67
JAVA基礎程式設計班 國立台灣大學 資訊工程學系暨研究所 資訊系統訓練班 講師:宋浩 [8] 例外與檔案處理

Transcript of JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤...

Page 1: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

JAVA基礎程式設計班

國立台灣大學 資訊工程學系暨研究所

資訊系統訓練班

講師:宋浩

[第8章] 例外與檔案處理

Page 2: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

章節目錄

8-1 例外處理

8-2 自訂例外

8-3 檔案處理

8-4 序列化處理

台灣大學 資訊工程系 資訊系統訓練班 2

Page 3: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

8-1 例外處理

台灣大學 資訊工程系 資訊系統訓練班 3

Page 4: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

例外處理(Exception-handling)

Java程式語言非常嚴謹,對程式的錯誤處理有一套很嚴謹的處理機制

除了在編譯時期嚴格的檢查原始碼可能產生的錯誤之外,在程式執行時期也提供了相關的處理機制,而這項機制稱為「例外處理機制(Exception-handling

Mechanishm)」

台灣大學 資訊工程系 資訊系統訓練班 4

Page 5: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

Java的例外與錯誤

程式執行時可能產生不正常的情況,而這不

常的情況可能是所謂的「例外」,比方說:

◦ 開啟一個不存在的檔案

◦ 除數為零

◦ 陣列的存取超出了索引值的範圍

◦ 未載入相關的套件即使用套件中的類別

台灣大學 資訊工程系 資訊系統訓練班 5

Page 6: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

為什麼要有例外?

台灣大學 資訊工程系 資訊系統訓練班 6

public class ReadFile { public void Read() { 開啟檔案; 決定檔案大小; 配置記憶體; 將檔案讀入記憶體; 關閉檔案; } }

指定檔案不存在

檔尾記號損毀,無法決定大小

記憶體不足

檔案毀損,讀檔失敗

檔案他人使用中,無法關閉

程式停止!

• 如果沒有例外處理…

Page 7: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 7

public class ReadFile { public int Read() { int ErrCode = 0; 開啟檔案; if (檔案存在) { 決定檔案大小; if (檔案大小已定) { 配置記憶體; if (記憶體足夠) { 將檔案讀入記憶體; if (讀入成功) { 開始操作檔案內容; } else { ErrCode = -1; } } else { ErrCode = -2; } } else { ErrCode = -3; } 關閉檔案; if (檔案無法關閉 && 無其它錯誤) ErrCode = -4; else ErrCode = -5; } else ErrCode = -6; return ErrCode; } }

用 if-else 來處理例外呢?

Page 8: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

Java 將所有的例外 (Exception),通通宣告成物件,且全部繼承 Throwable 物件

台灣大學 資訊工程系 資訊系統訓練班 8

Java 例外的概念 (1)

java.lang.Object

Throwable

Error Exception

RuntimeException … … …

… … …

… … …

CheckedException

Page 9: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

Java VM Errors ◦ 此區所發出的例外事件,JVM 會自行處理

Checked Exceptions ◦ 此區所發出的例外事件,是 Java 強迫要求程式師

一定要處理的,如不處理,則 Compile 時期就會發生錯誤訊息

Runtime Exceptions ◦ 此區所發出的例外事件,是使用者操作不小心所

引起的,程式師可處理可不處理,Java 並沒有硬性規定要攔截此類 Exception。

台灣大學 資訊工程系 資訊系統訓練班 9

Java 例外的概念 (2)

Page 10: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

常見 JVM Errors 介紹

Error

ThreadDeath VirtualMachineError

ThreadDeath: 當一個程式無預警停止時,就會發出此錯誤 VirtualMachineError: 當 JVM 內部出現無法解決的問題時,就會發出此錯誤

台灣大學 資訊工程系 資訊系統訓練班 10

Page 11: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

常見 Checked Exceptions 介紹

ClassNotFoundException:

◦ 當存取一個不存在或不正確的類別時,就會發出此例外

CloneNotSupportedException:

◦ 嘗試呼叫 .Clone(),但該類別並未支援時,會發出此例外

DataFormatException:

◦ 嘗試將一個資料指定給型態不符的物件時,就會發出此例外

IOException:

◦ 檔案不存在,或開檔不成功時,就會發出此例外

台灣大學 資訊工程系 資訊系統訓練班 11

Page 12: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

常見 Runtime Exceptions 介紹

例外名稱 例外狀況

ArithmeticException 分母為零時

IndexOutOfBoundsException 索引值超過物件上限時

ArrayIndexOutOfBoundsException 陣列索引值超過上限時 (子類別)

StringIndexOutOfBoundsException 字串索引值超過上限時 (子類別)

NegativeArraySizeException 當宣告陣列時,索引值為負數時

NullPointerException 呼叫了一個內容為 null 的變數

ArrayStoreException 陣列元素型態與陣列所宣告不合

ClassCastException 類別轉型 (Casting) 失敗

IllegalArgumentException 傳入參數型態不符

NumberFormatException parse 轉型失敗

台灣大學 資訊工程系 資訊系統訓練班 12

Page 13: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 13

對於Java而言,每個Exception都是一個物件。也就是說,當程式發生Exception時,就會產生某個特定的Exception物件。如果程式在執行時真的產生了異常情況,JVM會依照一定的程序來處理異常情況,過程如下:

1. 中止產生異常情況的指令的執行

2. 產生此異常情況的 Exception 物件

3. 如果設計者有撰寫處理該 Exception 的程式碼,則交由該區段的程式碼來處理;如果沒有設計處理的程式碼,則交由JVM處理

4. 如果是由JVM來處理 Exception 物件,則程式會異常終止

Java 的例外處理程序

Page 14: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 14

以下的範例顯示若沒有使用例外處理的語法時,程式會在產生例外的敘述上停止執行:

Java 的例外處理範例

程式9-1:Chap9\No Try.java

01: public class NoTry{

02: public static vod main (String[] args){

03: int count;

04:

05: String showName[]={

06: "Alex",

07: "Ivy",

08: "Fanny"

09: };

10:

11: for (count=0; count<4; count++){

12: System.out.println("第 "+count + 個名字是:"+showName[count]);

13: }

14: System.out.println("程式執行結束");

15: }

16: }

程式的執行結果為:

第 0 個名字是:Alex

第 1 個名字是:Ivy

第 2 個名字是:Fanny

Exception in thread "main" java.lang.

ArrayIndexOutOfBoundsException: 3

at NoTry.main (Notry.java:12)

Page 15: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

try-catch (1)

台灣大學 資訊工程系 資訊系統訓練班 15

「try-catch」是Java程式的例外處理敘述,該語法中的處理如下:

try

{

//可能產生例外的敘述

}

catch (ExceptionType E1)

{

//產生ExceptionType例外時,要處理的敘述

}

catch (Exception E2)

{

//產生其他的例外時,要處理的敘述

}

在語法「try」區段中包含了可能產生例外的程式碼。「catch」敘述後以「( )」表示需要處理的例外的類別,e1或是e2則是產生的例外物件。「catch」可以有多個區段,可分別用來處理不同的例外情況。當程式進入「try」區段執行敘述時,如果沒有發生例外,則程式會在執行完「try」區塊中的敘述後跳過所有的「catch」區段,繼續往下執行。如果在執行「try」區段中的敘述時產生例外,則程式會由例外的發生點跳出「try」區段,並嘗試進入第一個「catch」區段。如果該例外可以由該「catch」後的Exception類別處理,則程式會進入該「catch」區段,並執行相關的敘述。執行完畢後,程式不會再執行其他「catch」區段的判斷,而是直接跳出整個「try-catch」敘述。如果第一個「catch」區段無法處理(或稱為「捕捉」)該例外,程式會繼續執行其他的「catch」區段,並且判斷Exception類別。如果所有的「catch」區塊都無法捕捉程式產生的例外,JVM會停止該程式的執行

Page 16: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 16

以上一個「NoTry.java」範例加上捕捉例外的機制來示範如何撰寫「try-catch」:

程式9-2:Chap9\Try1.java

01: public class Try1 {

02: public static void main (String[] args){

03: int count;

04:

05: String showName[] = {"Alex","Ivy","Fanny"};

06:

07: try{

08: for (count=0; count<4; count++){

09: System.out.println(showName[count]);

10: }

11: } catch (ArrayIndexOutOfBoundsException e){

12: System.out.println(e.toString());

13: System.out.println("陣列索引超範圍");

14: } catch (Exception e){

15: System.out.println("其餘的錯誤" + e.getMessage());

16: }

17: System.out.println("程式執行結束");

18: }

19: }

try-catch (2)

Page 17: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 17

程式的執行結果為:

try-catch (3)

Alex

Ivy

Fanny

java.lang.ArrayIndexOutOfBoundsException: 3

陣列索引超範圍

程式執行結束

範例程式中將列印字串陣列的內容放在「try」區段中,由上一個範例得知在迴圈執行時會產生 「ArrayIndexOutOfBoundsException」的例外。因此在第一個「catch」區段中試圖捕捉該例外,而「e」是當捕捉到這個例外時所產生的物件。程式的第12

行使用了「toString()」方法來列印出該例外的相關訊息。程式執行時也有可能會產生我們在設計時無法得知的例外。因此第二個「catch」區段嘗試捉「Exception」類別的例外,因為這個類別是所有例外的父類別,所以如果程式產生了不同於「ArrayIndexOutOfBoundsException」例外而第一個「catch」區段無法捕捉到時,此區段會負責捕捉其他的例外

我們可以從程式的執行結果得知,程式在執行完第11~13行的例外處理後,並不會再執行第14和15行中的敘述而是直接跳離整個「try-catch」區塊,且執行第17行的敘述

Page 18: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

catch 區段的順序

台灣大學 資訊工程系 資訊系統訓練班 18

在上述的範例程式中,如果刪除第11~13行的程式,那執行的結果會是:

Alex

Ivy

Fanny

其餘的錯誤3

程式執行結束

其中的「3」是第15行程式中的「getMessage()」方法所產生的訊息。必需注意的是因為「Exception」類別是所有例外的父類別,因此不可以將「Exception」類別放在第一個「catch」區段中,除非只使用一個「catch」區段。若將上一個範例程式的順序修改:

} catch (Exception e) {

System.out.println("其餘的錯誤" + e.getMessage());

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println(e.toString());

System.out.println("陣列索引超出範圍");

}

因為「Exception」類別會捕捉所有的「Checked Exception」。因此第二個「catch」區段並無作用,所以該程式在編譯時會產生「exception.java.lang.ArrayIndexOutOfBoundsException has already been caught」的錯誤

Page 19: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

finally 區塊 (1)

台灣大學 資訊工程系 資訊系統訓練班 19

程式在執行「try」區段時,如果產生例外,則程式會跳到相關的「catch」區段去處理,並在處理完成後,再直接跳出「try-catch」區段。也因此「try」區段中產生例外的程式行以下的程式碼並不會被執行。這樣的執行流程可能會產生一些問題。例如:如果你打算在「try」區段中撰寫開檔、寫入、關檔等程序,但程式在進行寫入的動作時產生了例外,那「關檔」的動作就無法執行了。因此「try-catch」敘述中還提供了「finally」區段來保證某此程式碼一定可以執行

只要設計了「try-catch」機制,「finally」區段是一個不論例外是否發生,它都一定會執行的一個區段。如果你打算在「try」區段中撰寫開檔,寫入、關檔等程序,那可以將開檔、寫入的動作放在「try」區段中,而將「關檔」的動作寫在「finally」區段中,以確定在「寫入」的動作產生了例外時,還可以關閉開啟的檔案

要是你擔心如果在「開檔」的動作就產生例外,而程式在「finally」區段中無法關閉未開啟的檔案時,還可以在「finally」區段中再設計「try-catch」區段來捕捉這項例外

Page 20: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 20

參考以下的範例,並了解「finally」區段的執行情形:

finally 區塊 (2)

程式9-3:Chap9/try2.java

01:public class Try2 {

02: public static void main(String[] args){

03: int i, j, result;

04:

05: i = 100;

06: j = 0;

07:

08: try{

09: result = i / j;

10: } catch (ArithmeticException e){

11: System.out.println("除數不得為零");

12: } catch (Exception e){

13: System.out.println("其餘的錯誤");

14: } finally {

15: System.out.println("執行finally區段");

16: }

17: System.out.println("程式執行結束");

18: }

19: }

Page 21: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 21

finally 區塊 (3)

程式的執行結果為:

除數不得為零

執行finally區段

程式執行結束

範例程式的第6行中,特地將「j」的值設定為0,因此程式第9行執行時會產生「ArithmeticException」的例外。在執行完第11行的敘述後,程式會再執行第14-15行的「finally」區段的內容,最後再執行第17行的程式碼

Page 22: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 22

修改第6行的敘述改為「j = 10」,雖然不會有例外產生,但程式仍然會執行第14~15行

finally 區塊 (4)

程式9-3:Chap9/try2.java

01:public class Try2 {

02: public static void main(String[] args){

03: int i, j, result;

04:

05: i = 100;

06: j = 10;

07:

08: try{

09: result = i / j;

10: } catch (ArithmeticException e){

11: System.out.println("除數不得為零");

12: } catch (Exception e){

13: System.out.println("其餘的錯誤");

14: } finally {

15: System.out.println("執行finally區段");

16: }

17: System.out.println("程式執行結束");

18: }

19: }

執行finally區段

程式執行結束

因此,執行的結果會是:

Page 23: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 23

finally 區塊 (5)

雖然「try-catch」機制中「finally」是不管例外是否產生它都一定會執行的區段,但是在特殊的情況下「finally」區段仍然有可能會無法執行完該區段中的所有程式碼。唯一會導致「finally」區段不執行的情況是JVM不再執行,例如:呼叫「System.exit(0)」或是電腦當機。如果以上述的範例為例,如果我們在「finally」區段中加上「System.exit(0)」的敘述,如下列所示:

finally {

System.exit(0);

System.out.println("執行finally區段");

}

那程式執行結果就會變成:

除數不得為零

實際上該程式在執行完「System.exit(0)」時就已經執行完畢了,所以「finally」區段中的第二行敘述當然就不會再被執行了

Page 24: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 24

finally 區塊 (6)

最後,我們將「finally」區段做個總整理,如果有下列的程式碼:

//敘述一

try {

//敘述二

} catch (Exception e) {

//敘述三

} finally {

//敘述四

}

如果有以下的情況發生,敘述四執行的狀況分別為:

1. 如果敘述一產生例外,則敘述四不會執行

2. 不管敘述二是否產生例外,敘述四都會執行

3. 不管敘述三是否產生例外,敘述四都會執行

Page 25: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

throws 敘述 (1)

台灣大學 資訊工程系 資訊系統訓練班 25

Java程式語言要求programmer必需自行處理可能產生Checked Exception的程式碼。但其實當例外產生時,你也可以不要使用「try-catch」機制立即處理它。可以取代的作法是:將它「丟(throws)」出來給另一支程式處理。如果要使用這種方法,則必需使用「throws」關鍵字。參考以下的範例:

程式9-4:Chap9/Throws1.java

01:public class Throws1 {

02: public static void main(String[] args){

03: int a = 10, b = 0;

04: double result = 0;

05: try{

06: result = calculate(a, b);

07: } catch (ArithmeticException e){

08: System.out.println("除數不得為零");

09: } catch (Exception e){

10: System.out.println("其他的例外");

11: }

12: System.out.println("result的值為:" + result);

13: System.out.println("程式執行結束");

14: }

15:

16: public static double calculate(int i, int j) throws ArithmeticException{

17: return i/j;

18: }

19: }

Page 26: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 26

throws 敘述 (2)

程式執行結果為:

除數不得為零

result的值為0

程式執行結束

注意範例程式中第16行calculate方法的宣告方式。該方法會傳回兩數相除的結果,預估該方法可能產生除數為零的情況。但在「calculate」方法中,我們並沒有撰寫捕捉例外的程式碼,而是使用了「throws」關鍵字將例外丟出。此時呼叫該方法的程式區段就必需撰寫「try-catch」來捕捉可能產生的例外。這就是第5到第11行程式使用「try-catch」的原因

請注意:使用throws並不代表方法一定會丟出例外。範例程式中是因為我們特地將除數設定為0,calculate方法才會丟出例外。請自行將第3行程式中的b設定為非0的數值,例如:1。程式的執行結果會是:

result的值為:10.0

程式執行結束

Page 27: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 27

方法中的程式碼在執行的過程中可能會產生不只一種類型的例外,你可以使用逗號將各種例外區隔開來以便處理不同類型的例外。例如:

throws 敘述 (3)

public static double calculate(int i, int j)

throws ArithmeticException, Exception{

//相關程式碼;

}

或者也可以直接將所有可能產生的例外物件都轉型成Exception物件,例如:

public static double calculate (int i, int j)

throws Exception{

//相關程式碼;

}

範例程式中如果直接將「ArithmeticException」的例外物件轉型為「Exception」的例外物件,程式的執行結果仍會是相同的

有一點必需要知道的是:「Throws1.java」中的calculate()方法丟出來的ArithmeticException例外是屬Runtime Exception。這類型的例外也可以不需要自行捕捉,程式也可以通過編譯。因此即使main()方法中只有:

double result = calculate (a, b)

System.out.println("程式執行結束");

這兩行敘述,程式依然可以通過編譯。只是當例外產生時程式會不正常的終止

Page 28: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 28

如果方法中丟出來的例外是屬於Checked Exception,在呼叫該方法時就不能不去處理它。否則,程式在編譯時就會產生「unreported exception」的編譯錯誤。例如:

程式9-5:Chap9/Throws2.java

01:public class Throws2 {

02: public static void main(String[] args){

03: tryToAccess();

04: System.out.println("程式執行結束");

05: }

06:

07: public static void tryToAccess()

08: throws IOException{

09: System.out.println("嘗試使用Method");

10: }

11: }

則必需在呼叫tryToAccess()方法時使用「try-catch」程式才能通過編譯。例如:

try{

tryToAccess();

} catch (IOException e){}

throws 敘述 (4)

Page 29: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

Call Stack機制

台灣大學 資訊工程系 資訊系統訓練班 29

在宣告方法時,如果使用了「throws」關鍵字將可能產生的例外丟出,那麼呼叫此方法的類別就必需使用「try-catch」來補捉例外。這種將例外一直往上層丟出,直到該例外被處理為止的機制就稱為「Call Stack」機制。但如果呼叫此方法的類別又沒有處理產生的例外時,程式會發生什麼樣的情況呢?請參考下圖:

假定主程式「main()」呼叫「A( )」方法,而「A( )」方法中又呼叫了「B( )」方法,而「B( )」方法中又呼叫了「C( )」方法,但目前,各方法中都沒有設計「try-catch」的機制。如果「C( )」方法中產生了例外,此例外會往上丟給「B( )」方法處理。如果無法處理,該例外會再丟給「A( )」方法來處理。同樣的,「A( )」如果無法處理,該例外會再丟給「main( )」方法來處理。最後則由JVM來處理接到的例外並且中止程式的執行

Page 30: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

8-2 自訂例外

台灣大學 資訊工程系 資訊系統訓練班 30

Page 31: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

使用throw關鍵字 (1)

台灣大學 資訊工程系 資訊系統訓練班 31

雖然Java語言已經提供了相當多的例外類別,但有時候,為了設計出更User Friendly的程式,我們可能需要自己設計例外處理的機制。在探討如何自定例外之前,我們要先了解throw關鍵字的使用

「throw」關鍵字用在方法的內部,請不要和用於方法宣告時的「throws」關鍵字混為一談。如果在方法內部想要丟出例外的類別物件時需使用「throw」關鍵字。為了能夠自定例外類別,我們先了解Exception類別產生物件的方式。常用的Exception類別的建構子有:

建構子 作用

Exception() 建立一個Exception

Exception(String message) 建立一個Exception物件,並指定例外訊息為message

Exception

(String message, Throwable cause)

建立一個Exception物件,並指定例外訊息為message,同時將產生例外的原因cause傳入

Exception(Throwable cause) 建立一個Exception物,同時將產生例外的原因cause傳入

throw關鍵字可以用來丟出例外物件,它可以丟出Java內部的例外物件,也可以丟出自定的例外物件,throw的語法如下:

throw 例外物件; //丟出Java例外物件

throw new Exception ("自定的例外訊息"); //丟出匿名的例外物件

Page 32: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 32

使用throw關鍵字 (2)

程式9-6 : Chap9\Throw1.java

01: public class Throw1{

02: public static void main(String[] args) {

03: tryToCalculate(10, 0);

04: tryToCalculate(10, 2);

05: }

06:

07: public static void tryToCalculate(int x, int y) {

08: if (y == 0) {

09: try {

10: throw new Exception("Divided by Zero!!!");

11: }catch (Exception e) {

12: System.out.println(e.toString());

13: }

14: } else {

15: System.out.println("The Result is : " + x / y);

16: }

17: }

18: }

執行的結果為:

Page 33: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 33

範例程式在第10行使用了throw來丟出一個自定的例外物件,因為throw會產生例外物件,所以程式必需使用「try-catch」來捕捉產生的例外。Exception中的「除數不得為零!!!」的訊息會在例外物件產生時傳入該物件中。你也可以不需要直接處理這個例外物件,但是要再將這個物件丟出來,例如改寫範例程式的第11~13行為:

使用throw關鍵字 (3)

catch (Exception e) {

throw e;

}

如果是用這樣的處理方式,則必需要有另一個程式來呼叫main方法,並且在該程式中使用「try-catch」來處理例外

Page 34: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 34

01: class MyException extends Exception{

02: private int value;

03: MyException (int value){

04: this.value = value;

05: }

06: public String toString(){

07: String s = "本程式執行無效\n" +

08: "錯誤代碼為 " + value + " \n" +

09: "請將此代碼告知管理人員\n";

10: return s;

11: }

12: }

自定例外類別 (1)

MyException類別繼承自Exception類別,第3行的建構子需要傳入一個整數值當作是自定的錯誤代碼。程式的第6~11行改寫了toString()方法,新的toString()方法會顯示出錯誤代碼及相關的訊息

Page 35: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 35

自定例外類別 (2)

再來,以下的程式碼示範如何丟出MyException類別的例外訊息:

01: public static void tryToCalculates (int x, int y){

02: if (y == 0){

03: try{

04: throw new MyException(0);

05: } catch (MyException e){

06: System.out.println(e.toString());

07: }

08: } else {

09: System.out.println("結果為: " + x / y);

10: }

11: }

tryToCalculates(int x, int y)方法會計算兩數相除的結果,但是除數y不可以為0,如果y

的值為0,在程式的第4行會丟出MyException類別的例外,並指定錯誤代碼為0。程式的第5行會捕捉這個例外物件,並且在第6行利用toString()方法顯示錯誤訊息

Page 36: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 36

自定例外類別 (3)

main()的內容:

程式9-7:Chap9/Throws2.java

01: public class Throw2{

02: public static void main (String[] args) {

03: tryToCalculates(10, 0);

04: tryToCalculates(10, 2);

05: }

06: }

程式的執行結果為:

第3行的程式碼由於傳入的參數會導致除數為0的情況,該行程式會引發們定的MyException例外物件,並顯示自訂的錯誤訊息

Page 37: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

課堂練習 PT81

例外練習 (PT81.java):

設計一個程式在執行時需要輸入一個整數數值。

請考慮可能產生的例外情況,例如:未輸入數值,數值格式不正確等情形。如果例外產生,請使用throw 的方式直接丟出例外,並顯示相關訊息。如果沒有例外產生,請利用該數值計算正方形的面積。

台灣大學 資訊工程系 資訊系統訓練班 37

Page 38: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

8-3 檔案處理

台灣大學 資訊工程系 資訊系統訓練班 38

Page 39: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

串流

串流 (Stream)

◦ 將各類儲存媒體 (Floppy, HDD, CD-ROM…) 內的資料,統一成固定格式,以利讀取與寫入。

台灣大學 資訊工程系 資訊系統訓練班 39

輸入串流

輸出串流

Page 40: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

File 類別 (1)

台灣大學 資訊工程系 資訊系統訓練班 40

在 JAVA 中,檔案的讀、寫、在螢幕上顯示訊息、記憶體的存取,或是網路資源的使用等動作,都被視為「串流(Stream)」。「串流」可以被視為資料輸出、輸入的通道

JAVA 將處理串流資料的相關類別放於「java.io」套件之中,需事先引用這個套件

在實際探討串流資料處理之前,我們先來了解「File」類別。嚴格說來,它並不屬於串流的類別,因為該類別中的方法並不會牽涉到檔案的讀寫,但該類別會被用來提供檔案或是目錄的相關資訊,包括了檔案的建立,大小、修改日期、存取權限等資訊…

等等。File類別包含了三種型態的建構子:

建構子 作 用

File(String pathname, String filename) 以上層的路徑名稱parent,並以「filename」字串的內容為檔案名稱,建立新的File物件

File(String pathname) 將「pathname」的內容轉換為絕對路徑,並在該路徑下建立新的File物件

File(Object parent, String child) 以上層的路徑物件parent,以「child」字串的內容為子目錄的路徑或名稱,建立新的File物件

Page 41: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 41

在目前的目錄下建立一個參考到「test.txt」檔案的File物件:

File 類別 (2)

File f1 = new File("test.txt");

File類別也可以用來處理目錄,例如:

File f2 = new File("c:\\TestDir");

如果是在Windows系統下,該程式碼會產生一個指向「c:\TestDir」目錄的物件。會使用到「\\」是因為在Windows系統下的目錄符號「\」剛好是Java中跳脫字元的前置符號,所以使用了「\\」來代替實際的「\」符號。當然,如果你是要在Linux平台下執行Java程式,那目錄符號要更改為「/」

你也可以直接參考到指定目錄下的檔案,例如在windows系統下以下的兩行程式都會參考到「c:\TestDir\test.txt」檔案:

File f3 = new File("c:\\TestDir\\test.txt");

File f4 = new File("c:\\TestDir","test.txt");

或者產生一個參考到目錄的 File 物件,再利用該物件參考到檔案,例如:

File f5 = new File("c:\\TestDir");

File f6 = new File( f5, "test.txt");

Page 42: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

File類別的方法 (1)

台灣大學 資訊工程系 資訊系統訓練班 42

File類別也提供相當多的方法來處理檔案或是目錄,有些方法單用於目錄或是檔案,有些方法則是可以共用,請參考下表:

方 法 作 用

boolean canRead() 判斷是否可以根據提供的路徑讀取指定的檔案。如果可以,則傳回true,如果不可以,則傳回false。

boolean canWrite() 判斷是否可以根據提供的路徑寫檔。如果可以,則傳回ture,如果不可以,則傳回false。

boolean exists() 判斷指定的路徑下是否有指定的檔案

File getAbsoluteFile() 根據File物件參考的內容,取得指定的檔案參考

String getAbsolutePath() 根據File物件參考的內容,取得檔案的絕對路徑

String getName() 根據File物件參考的內容,取得目錄或是檔案的名稱,但不會包含路徑

String getParent() 根據File物件參考的內容,取得上一層的路徑名稱

boolean isDirectory() 根據File物件參考的內容,判斷是否為目錄

boolean isFile() 根據File物件參考的內容,判斷是否為檔案

long lastModified() 根據File物件參考的內容,取得該檔案最後被修改的日期,傳回毫秒值,並以1970年一月一日零時為計算基準,如果傳回OL,代表該檔案不存在

long length() 根據File物件參考的內容,取得檔案的長度

File[] listFiles() 根據File物件參考的內容,取得該路徑下所有的檔案名稱

boolean renameTo(File dest) 將File物件參考的內容更改為指定的dest名稱

Page 43: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 43

通常我們會先用isFile方法來判斷物件是否為檔案,再利用相關的方法來操作其他的需求:

File類別的方法 (2)

程式10-2:Chap 10\File 2.java

01: import java.io.File;

02: import java.util.Date;

03:

04: class File2{

05: public static void main(String[] args) {

06: File f = new File("c:\\Work\\Chap10\\Test.java");

07: System.out.println("f物件是否存在:"+ f.exists());

08: System.out.println("f物件是否為檔案:"+ f.isFile());

09: System.out.println("f物件是否可以讀取:"+ f.canRead());

10: System.out.println("f物件是否可以寫入:"+ f.canWrite());

11: System.out.println("f物件的實際名稱為:"+ f.getName());

12: System.out.println("f物件的修改日期為:"+ new Date(f.1astModified());

13: System.out.println("f物件的實際大小為:"+ f.length() +"Bytes");

14: System.out.println("f物件的絕對路徑為:"+ f.getAbsolutePath());

15: System.out.println("f物件的路徑為:"+ f.getParent());

16: }

17: }

程式的執行結果為: f物件是否存在:true

f物件是否為檔案:true

f物件是否可以讀取:true

f物件是否可以寫入:true

f物件的實際名稱為:Test.java

f物件的修改日期為:Sun Oct 30 12:20:30 CST 2005

f物件的實際大小為:104 Bytes

f物件的絕對路徑為:c:\Work\Chap10\Test.java

f物件的路徑為:c:\Work\Chap10

Page 44: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 44

File類別的方法 (3)

用 java 模擬 Windows 的 dir 指令,或 Unix 的 ls 指令:

程式10-3:Chap 10\File 3.java

01: import java.io.File;

02:

03:

04: class File3{

05: public static void main(String[] args) {

06: File f = new File("C:\\java\\");

07: File[] lists = f.listFiles();

08: int i ;

09:

10: for (i = 0 ; i<lists.legngth-1 ; i++) ;

11: if (lists[i].isDirectory()) {

12: System.out.println("<Dir>\t");

13: } else {

14: System.out.println(lists[i].getName()+"\t"+lists[i].length()+"Bytes");

15: }

16: }

17: }

18: }

執行的結果類似:

File1 .class 680 Bytes

File1 .java 319 Bytes

File2 .class 1587 Bytes

File2 .java 729 Bytes

Page 45: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 45

import java.io.*;

public class FileRename

{

public static void main(String[] args)

{

File fs = new File(args[0]);

File fd = new File(args[1]);

if (fs.exists())

{

if (!fd.exists())

{

if (fs.renameTo(fd))

{

System.out.println(fs.getName() + " 已改名為 " + fd.getName());

System.out.println("1 file(s) has been renamed!");

}

}

}

}

}

File類別的方法 (4)

更改檔名:

Page 46: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

字元串流的處理

JAVA 的緩衝處理

◦ 緩衝資料流(Buffered Stream)

◦ 藉由一塊記憶體緩衝區來連結I/O資料流,並讓資料的操作能夠增加效能

相關類別

◦ InputStreamReader

◦ BufferedReader

台灣大學 資訊工程系 資訊系統訓練班 46

Page 47: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 47

BufferedReader (1)

我們也可以使用BufferedReader來儲存自鍵盤輸入的資料,藉由該類別中的readLine方法可以一次讀取整行的資料,請參考以下的範例:

程式10-8:Chap 10\ InputStreamReader 2.java

01: import java.io.*;

02:

03: public class InputStreamReader 2 {

04: public static void main(String[] args) {

05: InputStreamReader ir = new InputStreamReader(System.in);

06: BufferedReader br = new BufferedReader(ir);

07: float salary;

08:

09: try{

10: System.out.print("請輸入月薪:");

11: salary = Float.parseFloat(br.readLine());

12: System.out.print("你的年薪是:"+salary*12);

13: } catch (IOException e) {

14: System.out.println(e.toString());

15: } catch (Exception e) {

16: System.out.println(e.toString());

17: }

18: }

19: }

Page 48: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 48

程式的執行結果為:

請輸入月薪:35

你的年薪是:420.0

程式的第6行將InputStreamReader物件轉為BufferedReader物件,而在程式的第11行則使用readLine方法來讀取輸入的整行資料。由於讀入的資料是String型態的資料,所以,再使用「Float.parseFloat()」方法來將資料轉為float型態

BufferedReader (2)

Page 49: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

課堂練習 PT82

串流練習 (PT82.java):

以 InputStreamReader 寫一個程式可以分別詢問使用者他的:

◦ 名字

◦ 年齡

◦ 性別

輸入完後再將結果印在畫面:

Hi 名字 (先生/小姐) 你好,你今年 年齡 歲

台灣大學 資訊工程系 資訊系統訓練班 49

Page 50: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

讀寫檔案

JAVA 中讀寫檔案的方法有許多種

在此介紹英文與中日韓文語系中最常使用的兩種類別工具:

◦ 英文讀寫:

DataInputStream / DataOutputStream

◦ 中日韓文讀寫:

FileReader / FileWriter

台灣大學 資訊工程系 資訊系統訓練班 50

Page 51: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

Input/Output Stream

台灣大學 資訊工程系 資訊系統訓練班 51

DataInputStream和DataOutputStream類別是位元資料處理的串接類別。DataInputStream與DataOutputStream須藉由FileInputStream與

FileOutputStream對檔案做存取

假設有一檔案 file1.txt 內容為:

Page 52: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

DataInputStream

台灣大學 資訊工程系 資訊系統訓練班 52

以下的範例示範如何使用DataInputStream類別,並讀取「file1.txt」檔案中的資料:

程式10-14:Chap 10\ DataInputStream1.java

import java.io.*;

class DataInputStream1

{

public static void main(String[] args) throws IOException

{

FileInputStream fis = new FileInputStream("file1.txt");

DataInputStream dis = new DataInputStream(fis);

int i;

while((i = dis.read()) != -1)

{

System.out.print((char) i);

}

dis.close();

fis.close();

}

}

程式的執行結果為: You will always on my mind.

?_?·?????F??±x???n??

Page 53: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 53

DataOutputStream

以下的範例示範如何使用DataOutputStream類別,並將資料寫入「File2.txt」檔案中:

程式10-15:Chap 10\ DataOutputStream 1.java

01: import java.io.*;

02:

03: public class DataOutputStream 1 {

04: public static void main (String[] args) throws IOException {

05: FileOutputStream fos = new FileOutputStream("file2.txt");

06: DataOutputStream dos = new DataOutputStream(fos);

07:

08: byte[] c = {'J', 'a', 'v', 'a'};

09: dos.write( c);

10:

11: fos.close();

12: dos.close();

13: }

14: }

範例程式的第5行建構出一個FileOutputStream物件,並將此物件傳給DataOutputStream

物件。程式的第9行使用「write()」方法將資料寫入「File2.txt」檔案中

Page 54: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

FileReader/FileWrite類別

台灣大學 資訊工程系 資訊系統訓練班 54

不論是FileInputStream、FileOutputStream、DataInputSteam、DataOutputStream類別,它們都是針對位元組資料所設計的類別。對於亞洲體系的文字,由於使用的是雙位元的資料,這些類別並無法很完善的處理這些類型的資料。如果要處理雙位元的資料,我們必需使用FileReader、BufferedReader、FileWrite、BufferedWriter等類別。處理方式請參考下圖:

File 類別

File 類別

Page 55: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 55

FileReader 類別 以下的範例示範如何使用FileReader類別,並讀取「file1.txt」檔案中的資料:

程式10-16:Chap 10\ FileReader1.java

01: import java.io.*;

02:

03: public class FileReader1 {

04: public static void main (String[] args) throws IOException {

05: File f = new File("file1.txt");

06: FileReader fr = new FileReader(f);

07: int i;

08:

09: while((i = fr.read()) !=-1) {

10:

11: System.out.print((char) i);

12: }

13: fr.close();

14: }

15: }

程式執行的結果為:

You will always on my mind.

北風傳來了熟悉的聲音

Page 56: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 56

FileWriter 類別

以下的範例示範如何使用FileWrite類別,並將字串寫入「file3.txt」檔案中的資料:

程式10-17:Chap 10\ FileWriter 1.java

01: import java.io.*;

02:

03: public class FileWriter 1 {

04: public static void main (String[] args) throws IOException {

05: File f = new File("file3.txt");

06: FileWriter fw = new FileWriter(f);

07:

08: String str = "Java is easy to learn.\n";

10:

11: fw.write(str);

12: fw.close();

13: }

14: }

Page 57: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 57

檔案輸出入練習 (PT83.java): 假定某位學生的紀錄如下:

姓名:name,字串型態,值為「Alex」

數學成績:mathRecord,int型態,值為「95」

國文成績:chnRecord,int型態,值為「90」

英文成績:engRecord,int型態,值為「94」

請建構串流物件out,並將該筆記錄寫入「record.txt」檔案中,再將「record.txt」檔案的內容讀出,並顯示在螢幕上

課堂練習 PT83

Page 58: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

8-4 序列化處理

台灣大學 資訊工程系 資訊系統訓練班 58

Page 59: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

序列化:

◦ 將物件寫進串流中

◦ ObjectInputStream

反序列化:

◦ 將被寫進串流中的物件讀出

◦ ObjectOutputStream

要序列化某個類別,則該類別須實作

Serializable 介面

台灣大學 資訊工程系 資訊系統訓練班 59

序列化處理 (1)

Page 60: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 60

序列化的處理 (2)

程式10-18:Chap 10\ Employee.java

01: import java.io.*;

02:

03: public class Employee implements Serializable {

04: private String name;

05: private String ID;

06: private float salary;

07:

08: Employee(String name , String ID , float salary) {

09: this.name = name;

10: this.ID = ID;

11: this.salary = salary;

12: }

13: public String getName(){

14: return name;

15: }

16: public String getID() {

17: return ID;

18: }

19: public float getSalary() {

20: return salary;

21: }

22: }

Page 61: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 61

程式10-19:Chap 10\ WriteData.java

01: import java.io.*;

02:

03: public class WriteData {

04: public static void main(String[] args) {

05: Employee[] s = new Employee[2];

06:

07: s[0] = new Employee("Alex" ,"001" , 32000.f);

08: System.out.println(s[0].getName());

09: System.out.println(s[0].getID());

10: System.out.println(s[0].getSalary());

11:

12: s[1] = new Employee("Ivy","002", 43000.f);

13: System.out.println(s[1].getName());

14: System.out.println(s[1].getID());

15: System.out.println(s[1].getSalary());

16:

17: try{

18: FileOutputStream fs = new FileOutputStream("Employee.txt");

19: ObjectOutputStream out = new ObjectOutputStream(fs);

20: out.writeObject(s);

21: out.close();

22: fs.close();

23: } catch (IOException e){

24: System.out.println(e.toString());

25: }

26: }

27: }

序列化的處理 (3)

Page 62: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 62

程式的執行結果為:

序列化的處理 (4)

Alex

001

32000.0

Ivy

002

43000.0

程式執行後你會在目錄下找到「Employee.txt」文字檔,但無法直接瀏覽該檔的內容

範例程式的第5行宣告一個Employee陣列,可用來儲存2筆資料。而程式的第7~15行分別建立Employee物件,並且將物件的內容顯示在螢幕上。程式的第18~22行是本範例程式的重點。第18行宣告了一個FileOutputStream物件,用來將內容寫入Employee.txt檔案中。再於第19行程式中將FileOutputStream物件傳遞給ObjectOutputStream,並建立新的ObjectOutputStream物件。第20行程式中,使用ObjectOutputStream物件的WriteObject方法將Employee陣列的內容寫入Employee.txt檔案中。寫入的方式很簡單,但請注意,程式中寫入Employee陣列的資料,因此在讀取資料時,也必需將檔案的內容輸入Employee陣列中,否則會因型態不符而產生classCastException的例外

Page 63: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 63

序列化的處理 (5)

程式10-20:Chap 10\ ReadData.java

01: import java.io.*;

02:

03: public class ReadData {

04: public static void main(String[] args) {

05: try{

06: FileInputStream fs = new FileInputStream("Employee.txt");

07: ObjectInputStream in = new ObjectInputStream(fs);

08:

09: Employee[] s = (Employee[] ) in.readObject();

10:

11: for(int i = 0 ; i<s.length; i++) {

12: System.out.println(s[i].getName());

13: System.out.println(s[i].getID());

14: System.out.println(s[i].getSalary());

15: }

16: in.close();

17: fs.close();

18: } catch (Exception e) {

19: System.out.println( e.toString());

20: }

21: }

22: }

Page 64: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

台灣大學 資訊工程系 資訊系統訓練班 64

序列化的處理 (6)

程式的執行結果為:

Alex

001

32000.0

Ivy

002

43000.0

Page 65: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

1. 庫存系統練習 (HW81.java): 假設有一個庫存系統,在存貨類別的處理方面,庫存的計算可能會有兩例外狀態:一種是庫存數量小於0(NegativeStockException),另一種是需要提出的貨品數量大於庫存量(ShortStockExctpion)

請設計上述兩個例外類別,並使用throw來測試例外。

2. 存款利息計算程式 (HW82.java) : 假定有以下的資料型態:

請設計一個程式,使用者可以由鍵盤依次輸入上述的資料,輸入完成後,再將輸入的內容顯示在螢幕上,並依輸入的本金和利率,再計算一年的存款利息

台灣大學 資訊工程系 資訊系統訓練班 65

String name; //儲存姓名的資料

float premium; //代表銀行存款的本金數額

float iRate; //代表銀行的存款利率

回家作業 – HW8 (1)

Page 66: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

回家作業 – HW8 (2)

3. 猜數字程式 v2 (HW83.java): 請改進 HW61.java的猜數字程式。以BufferedReader的方法讓使用者可以一直猜,直到猜對正確答案為止

台灣大學 資訊工程系 資訊系統訓練班 66

Page 67: JAVA基礎程式設計班 - csie.ntu.edu.twd99922028/java/Java272/20160818.pdfJava的例外與錯誤 程式執行時可能產生不正常的情況,而這不 常的情況可能是所謂的「例外」,比方說:

繳交回家作業

PT8 (課堂練習) 與 HW8 (回家作業) 請一起繳交

把相關 *.java 檔案以 zip 或 rar 壓縮並取名為「學號.zip」或「學號.rar」並附件到 email 中寄到:

◦ 主旨:[JAVA245][hw][8]姓名

◦ 收件人:[email protected]

Deadline:下一次上課前

台灣大學 資訊工程系 資訊系統訓練班 67