Java 入門指南 - 存檔與例外處理

我們要存檔,儲存的到底是什麼呢?物件 (object) 嗎?屬性 (field) 嗎?還有方法 (method) 呢?




Encrypt 類別完整的範例程式碼,請參考Encrypt.java
EncryptorGUI 類別完整的範例程式碼,請參考EncryptorGUI.java


Java 提供序列化的方式儲存物件,凡是可以被儲存的物件都得實作 java.io 的 Serializable 介面。因此,我們要使 Encrypt 型態的物件可以被儲存,就得在 Encrypt.java 中,先 import java.io
import java.io.*;


然後在 Encrypt 類別 implements Serializable
public class Encrypt implements Serializable {


這樣 Encrypt 就可以被序列化了,至於到底哪些東西被序列化存檔了呢?嗯,其實這點我們先不必擔心,因為被序列化的物件都可以解序列化,還原成本來的物件囉!記得,我們修改過 Encrypt ,因此 Encrypt.java 需要重新編譯。


若類別中有東西不打算被序列化存檔,就得在宣告時用關鍵字 transient 註明,這裡,我們的 Encrypt 並不會用到 transient


底下回到 EncryptorGUI 類別,繼續討論怎麼樣加入存檔功能唷!


我們用 Save 按鈕 (button) 執行存檔的工作,由 SaveListener 進行事件處理 (event handling)
// 儲存 Encrypt 物件檔案的事件
class SaveListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        JLabel t1 = (JLabel) GUIComponent.get(2);
        JTextField t2 = (JTextField) GUIComponent.get(4);
            
        try {
            FileOutputStream fs = new FileOutputStream("encryptor.ser");
            ObjectOutputStream os = new ObjectOutputStream(fs);
            os.writeObject(e);
            os.close();
            fs.close();
            t1.setText("This is Save button. Encrypt object is saved.");
        }
        catch (Exception ex) {
            ex.printStackTrace();
            t1.setText("This is Save button. Encrypt object is not saved.");
        }
        finally {
            t2.setText("after Save .....");
        }
    }
}


其中,從 199 行到 213 行
try {
    FileOutputStream fs = new FileOutputStream("encryptor.ser");
    ObjectOutputStream os = new ObjectOutputStream(fs);
    os.writeObject(e);
    os.close();
    fs.close();
    t1.setText("This is Save button. Encrypt object is saved.");
}
catch (Exception ex) {
    ex.printStackTrace();
    t1.setText("This is Save button. Encrypt object is not saved.");
}
finally {
    t2.setText("after Save .....");
}


這裡進行了例外處理 (exception handling) ,也就是說, Java 用 try-catch-finally 三個關鍵字 (keyword) 處理發生例外 (exception) 的狀況,其中, finally 的部份可有可無。


所謂的例外就是程式有可能出錯的地方,發生錯誤的原因並非來自程式的邏輯,而是一些其他的因素,例如想要開啟指定檔名的檔案,可是檔案並不存在。很多情況都可能導致程式無法繼續執行,例外處理提供錯誤發生後使程式繼續處理的機制。


凡是有可能發生例外的程式碼需要放在 try 後頭的大括弧中, catch 則是放發生例外後,程式如何去處理例外的情況, finally 的部份則是無論例外有沒有發生都會被執行的部份。


事實上, Java 並不會主動測知例外的發生,反倒是依賴設計建構子 (constructor) 或方法 (method) 時,建構子或方法是否有丟出例外,我們用到丟出例外的建構子或方法才需要處理例外,有丟出例外的建構子或方法使用 throws 關鍵字。


上述的例子, FileOutputStream() 用來建立輸出到檔案的串流 (stream) ,這會 throws FileNotFoundException 型態的例外,FileOutputStream() 的參數 (parameter) 字串 (string) 為檔案名稱。 ObjectOutputStream() 用來將物件送到指定的輸出串流,這也會丟出 IOException 型態的例外。


接下來的 writeObject() 便是將物件寫進到輸出串流中,會丟出 IOException 型態的例外,最後,檔案處理完關閉串流的 close() ,也是會丟出 IOException 型態的例外。


因此,這些程式碼都得放在 try 後頭的大括弧中。


Java 允許程式設計師不處理例外,這在方法宣告的地方加進關鍵字 throw 接例外名稱即可,可是不處理例外是很不負責任的行為,我們不建議這麼做 :)


Load 按鈕 (button) 執行載入檔案的工作,由 LoadListener 進行事件處理
// 載入已儲存 Encrypt 物件檔案的事件
class LoadListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        JLabel t1 = (JLabel) GUIComponent.get(2);
        JTextField t2 = (JTextField) GUIComponent.get(4);
            
        try {
            FileInputStream fs = new FileInputStream("encryptor.ser");
            ObjectInputStream is = new ObjectInputStream(fs);
            e = (Encrypt) is.readObject();
            is.close();
            fs.close();
            t1.setText("This is Load button. Encrypt object is loaded.");
        }
        catch (Exception ex) {
            ex.printStackTrace();
            t1.setText("This is Load button.  Encrypt object is not loaded.");
        }
        finally {
            t2.setText("after Load .....");
        }
    }
}


同樣的,大部分從檔案載入物件的工作也需要處理例外,這裡要留意一行
e = (Encrypt) is.readObject();


利用小括弧將從檔案讀到的物件強制轉換型態為 Encrypt ,如果不這麼做, e 會被當成 Object ,那 e 只能有 Object 所能具有的屬性跟方法哩!


我們來編譯執行看看吧!



先新建一個 Encrypt 物件



輸入 "There is no spoon." 編碼看看結果



儲存這個 Encrypt 物件



新建另一個 Encrypt 物件



重新編碼,結果會不一樣囉!



然後載入剛剛儲存的 Encrypt 物件



再次編碼,這就跟原先儲存 Encrypt 物件的結果一樣咧!



接下來,我們繼續未完的功能,看看完成版的 EncryptorGUI 吧!


中英文術語對照
物件object
屬性field
方法method
按鈕button
事件處理event handling
例外處理exception handling
關鍵字keyword
例外exception
建構子constructor
方法method
串流stream
參數parameter
字串string


您可以繼續參考
GUI 篇


相關目錄
回 Java 入門指南
回 Java 教材目錄
回首頁


參考資料
The JavaTM Tutorials: Getting Started
The JavaTM Tutorials: Learning the Java Language
The JavaTM Tutorials: Essential Classes
The Java Language Specification, Third Edition


本文於 2013 年 1 月訂正

沒有留言: