---
# System prepended metadata

title: try catch 之五 - try resources
tags: [java, article index, tutorial article, teaching]

---

```java
public class ExampleTryResources {

    public static void main(String[] args) {

        String path = "resources/poem.txt";

        /*
         * 第一個 try catch finally 是 Java7 前傳統的寫法
         * 因為 reader 本身也帶有 Checked Exception 屬性，所以必須特別處理他。
         * 
         * 但 BufferedReader 也需要 close, 所以才會產生
         * 在 try catch 外面指定成 null，到 try catch 內的時候才正式初始化的狀況。
         * 
         * 當程式執行結束後，到 finally 就會試著 close 這個物件。
         * 但 reader close 這件事同樣帶有 Checked Exception 屬性，
         * 所以在那邊還是要 try catch 包覆著那段程式
         */
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(path));
            String line = reader.readLine();
            while (line != null) {
                System.out.println(line);
                line = reader.readLine();
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        /* 
         * 在 Java 7 之後，可以使用 try-with-resources 來自動管理資源的關閉，
         * 不需要手動在 finally 區塊中進行 close 操作。
         * 這適用於實作了 AutoCloseable 或 Closeable 介面的類型。
         * 在下面這段程式碼中，BufferedReader 實作了 Closeable 介面，
         * 因此可以在 try-with-resources 中使用。
         * 這樣可以簡化程式碼並確保資源的正確關閉。
         * 
         * 跟第一段的傳統寫法相比，程式碼的內容明顯少了很多，維護起來也更方便。
         */
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
            String line = br.readLine();
            while (line != null) {
                System.out.println(line);
                line = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        /*
         * 若有多個 Closeable 的類別同時間實例化了，
         * 那可以照著實例化的依賴順序放進 try resources 的區塊內。
         */ 
        try (FileReader fr = new FileReader("input.txt");
                BufferedReader br = new BufferedReader(fr);
                FileWriter fw = new FileWriter("output.txt")) {
            String line;
            while ((line = br.readLine()) != null) {
                fw.write(line);
                fw.write("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        /*
         * 如果因為順序問題導致無法將所有 Closeable 的宣告放在第一層括號內，
         * 後續也可以繼續用 try resources 括號起來，
         * 也不需要特別 catch Exception。
         */ 
        try (
            FileReader fr = new FileReader("input.txt");
            BufferedReader br = new BufferedReader(fr);
            FileWriter fw = new FileWriter("output.txt")
        ) {
            String line;
            while ((line = br.readLine()) != null) {
                fw.write(line);
                fw.write("\n");
            }
            // 假設在 while 迴圈之後使用另一個 Closeable 的類別
            // 實際上沒有 OtherCloseable 這個 Class, 純粹舉例用
            try (OtherCloseable otherClazz = new OtherCloseable()) {
                // 使用 otherClazz 對文字做任何轉換處理
                String convertedText = otherClazz.dosomething(line);
            }            
        } catch (IOException e) {
            e.printStackTrace();
        }        
    }
}

```