天天看點

JAVA SE之面向對象14:IO流的基礎

今日内容:

  • IO流的概述
  • 異常處理機制
  • File類

1.IO流的引入及異常的概述和分類

  • IO流概述:

    IO流用來處理裝置之間的資料傳輸

    上傳檔案和下載下傳檔案,複制檔案

  • 異常的概述:

    Java程式在運作過程中出現的錯誤

  • 異常的分類及繼承體系:

    異常的基類: Throwable

    嚴重問題: Error

    不予處理,因為這種問題一般是很嚴重的問題,比如: 記憶體溢出

    非嚴重問題: Exception

    ​編譯時異常: 非RuntimeException

    運作時異常: RuntimeException

  • JVM預設是如何處理異常的?

    a.自己将該問題處理,然後繼續運作

    b.自己沒有針對的處理方式,隻有交給調用main的jvm來處理

    jvm有一個預設的異常處理機制,就将該異常進行處理.

    并将該異常的名稱,異常的資訊.異常出現的位置列印在了控制台上,同時将程式停止運作

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int[] arr = {2, 3, 4};
        //arr = null;
        Scanner scanner = new Scanner(System.in);
        System.out.println("請錄入整數");
        //有可能會發生多種異常,我們可以寫多個catch()來進行處理
        //能明确的異常類型,盡量明确,不要隻使用一個(Exception e) 一捕了之。
        //多個異常類型存在父子關系,父異常放在後面,并列關系的異常,誰前誰後都可以
        //try 裡面放的是,有可能會出現異常的代碼,不要放不相關的代碼。
        //catch(){} 裡面是你對異常的處理,記着不要做空處理,哪怕你列印一句話提醒下
        try {
            System.out.println(arr[8]);
            int i = scanner.nextInt();
            System.out.println(i);
            System.out.println(a / b);
        } catch (ArrayIndexOutOfBoundsException e) {
            // System.out.println("角标越界了");
            e.printStackTrace(); //列印資訊的異常資訊。
        } catch (ArithmeticException e) {
            System.out.println("初始為0");
            b = 200;
        } catch (NullPointerException e) {
            System.out.println("對象為null了");
        } catch (InputMismatchException e) {
            System.out.println("錄入類型錯誤的異常");
        } catch (Exception e) {
            // System.out.println("其他異常");
            e.printStackTrace();
        }

        System.out.println("下面的代碼");
        System.out.println("下面的代碼");
        System.out.println("下面的代碼");
        System.out.println("下面的代碼");
        System.out.println("下面的代碼");
        System.out.println("下面的代碼");


    }
}
           

3.異常處理方式

  • 異常處理的兩種方式
  • [ try…catch…finally ]
  • [ throws ]

3.1 try…catch的方式處理異常1

try	{
  	可能出現問題的代碼 ;
  }catch(異常名 變量名){
  	針對問題的處理 ;
  }finally{
  	釋放資源;
  }
  
  變形格式:
  	try	{
  		可能出現問題的代碼 ;
  	}catch(異常名 變量名){
  		針對問題的處理 ;
  	}
           
  • 注意事項:

    a.try中的代碼越少越好

    b.catch中要做處理,哪怕是一條輸出語句也可以.(不能将異常資訊隐藏)

  • 示範: try…catch…finally的方式處理1個異常
public class Test {
    public static void main(String[] args) {
        Scanner scanner = null;
        try {
            System.out.println(1 / 0);
            scanner = new Scanner(System.in);
            System.out.println("請輸入一個整數");
            int i = scanner.nextInt();
            System.out.println(i);
        } catch (InputMismatchException e) {
            System.err.println("輸入類型錯誤");
            //finally 的特點就是不管你try裡面的代碼有沒有發生異常,finally裡面的代碼都會執行,
            // 一般有些善後收尾的代碼可以放在finally來做
        } finally {
            //釋放資源
            System.out.println("finally 執行了");
            if (scanner != null) {
                scanner.close();
            }
        }
    }
}
           

3.2 異常處理方式:try…catch的方式處理異常2

try {
 可能出現問題的代碼 ;
}catch(異常名1 變量名1){
 對異常的處理方式 ;
}catch (異常名2 變量名2){
  對異常的處理方式 ;
}....
           

3.3 JDK7針對多個異常的處理方案

JDK1.7中對多個catch的變形格式

try {

 可能出現問題的代碼 ;

}catch(異常名1 | 異常名2 | ....   變量名){

對異常的處理方案 ;

}
           

好處: 就是簡化了代碼

弊端: 對多個異常的處理方式是一緻的

注意事項:

多個異常之間隻能是平級的關系,不能出現子父類的繼承關系

注意事項:

  • 處理方式是一緻的。(實際開發中,好多時候可能就是針對同類型的問題,給出同一個處理)
  • 多個異常間必須是平級關系。

4.編譯期異常和運作期異常的差別

  • Java中的異常被分為兩大類:編譯時異常和運作時異常
  • 所有的RuntimeException類及其子類的執行個體被稱為運作時異常,其他的異常就是編譯時異常;編譯時異常: Java程式必須顯示處理,否則程式就會發生錯誤,無法通過編譯。
  • 運作時異常: 無需顯示處理,也可以和編譯時異常一樣處理

5.Throwable的幾個常見方法

  • a.getMessage():

    擷取異常資訊,傳回字元串

  • b.toString():

    擷取異常類名和異常資訊,傳回字元串

  • c.printStackTrace():

    擷取異常類名和異常資訊,以及異常出現在程式中的位置。傳回值void。

5.1 throws的方式處理異常

  • throws的方式處理異常

    定義功能方法時,需要把出現的問題暴露出來讓調用者去處理。

    那麼就通過throws在方法上辨別。

  • 示範:舉例分别示範編譯時異常和運作時異常的抛出

5.2 throw的概述以及和throws的差別

  • throw的概述:在功能方法内部出現某種情況,程式不能繼續運作,需要進行跳轉時,就用throw把異常對象抛出。
  • 示範:分别示範編譯時異常對象和運作時異常對象的抛出
  • throws和throw的差別

    a.throws

    用在方法聲明後面,跟的是異常類名

    可以跟多個異常類名,用逗号隔開

    表示抛出異常,由該方法的調用者來處理

    throws表示出現異常的一種可能性,并不一定會發生這些異常

    b.throw

    用在方法體内,跟的是異常對象名

    隻能抛出一個異常對象名

    這個異常對象可以是編譯期異常對象,可以是運作期異常對象

    表示抛出異常,由方法體内的語句處理

    throw則是抛出了異常,執行throw則一定抛出了某種異常

5.3 finally關鍵字的特點及作用

  • finally的特點

    被finally控制的語句體一定會執行(前提 jvm沒有停止)

    特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))

  • finally的作用:

    用于釋放資源,在IO流操作和資料庫操作中會見到

5.4 finally關鍵字的面試題

  • 面試題1:final,finally和finalize的差別

final: 是一個狀态修飾符, 可以用來修飾類 , 變量 , 成員方法.

被修飾的類不能被子類繼承, 修飾的變量其實是一個常量不能被再次指派,修飾的方法不能被子類重寫

**finally:**用在try…catch…語句中 , 作用: 釋放資源 . 特點: 始終被執行(JVM不能退出)

finalize: Obejct類中的一個方法,用來回收垃圾

  • 面試題2:如果catch裡面有return語句,請問finally的代碼還會執行嗎?如果會,請問是在return前還是return後。

    答:會執行, 在return前

例子如下:
			try {
			System.out.println(23 / 0);
		} catch (Exception e) {
			System.out.println("哦,catch了...............");
			return ;
		}finally {
			System.out.println("哦,被執行了..............");
		}
           
代碼如下:
public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請錄入你的成績");
        double score = sc.nextDouble();
        isScore(score);
    }

    private static void isScore(double score) {
        if (score >= 0 && score <= 100) {
            System.out.println("成績合法");
        } else {
            throw new ScoreException("成績不合法");
        }
    }
}
           

6.自定義異常概述和基本使用

  • 為什麼需要自定義異常?

    因為在以後的開發過程中,我們可能會遇到各種問題,而Jdk不可能針對每一種問題都給出具體的異常類與之對應。

    為了滿足需求,我們就需要自定義異常。

  • 自定義異常概述 需要将我們自定義的異常類納入到我們的異常體系中

    繼承自Exception

    繼承自RuntimeException

  • 自定義異常的基本使用
// 判斷成績範圍
		if(score > 100 || score < 0){
			
			// 抛出一個異常對象
			//注意 自定義異常類 提供有參數構造 
			throw new MyException("成績不在有效的範圍内(0~100)....") ;
			
		}else {
			System.out.println("成績合法.....................");
		}
           

練習

  • 需求:從銀行取錢,發現錢不夠,給出提示。
代碼如下:

public class Test {
    static double money = 500;

    public static void main(String[] args) throws NullPointerException, IndexOutOfBoundsException {
        new ArrayList<>(-20);
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入取款金額");
        double v = scanner.nextDouble();
        //捕獲自定義異常
        try {
            withdrawal(v);
        } catch (NoMoneyException e) {
            e.printStackTrace();
        }
        System.out.println("下面代碼");
        System.out.println("下面代碼");
        System.out.println("下面代碼");


    }

    private static void withdrawal(double v) {
        if (v <= money) {
            money -= v;
            System.out.println("取款成功");
        } else {
            //餘額不足異常。
            //throw 抛出的自定義異常
            throw new NoMoneyException("餘額不足");
        }
    }
}
           

7.異常的注意事項及如何使用異常處理

  • A:異常注意事項(針對編譯期異常)

    (1).子類重寫父類方法時,子類的方法必須抛出相同的異常或父類異常的子類,或者子類不抛出異常也是可以的。(父親壞了,兒子不能比父親更壞)

    (2).如果父類抛出了多個異常,子類重寫父類時,隻能抛出相同的異常或者是他的子集,子類不能抛出父類沒有的異常,或者子類不抛出異常也是可以的。

    (3).如果被重寫的方法沒有異常抛出,那麼子類的方法絕對不可以抛出異常,如果子類方法内有異常發生,那麼子類隻能try,不能throws

  • B:如何使用異常處理

    原則:如果該功能内部可以将問題處理,用try,如果處理不了,交由調用者處理,這是用throws

    差別:

    後續程式需要繼續運作就try

    後續程式不需要繼續運作就throws

    如果JDK沒有提供對應的異常,需要自定義異常。

8.File類

8.1 File類的概述和構造方法

  • File類的概述

    檔案和目錄路徑名的抽象表示形式;

    可以用來表示檔案,也可以用來表示目錄

  • 構造方法

    File(String pathname):

    根據一個路徑得到File對象

    File(String parent, String child):

    根據一個目錄和一個子檔案/目錄得到File對象

    File(File parent, String child):

    根據一個父File對象和一個子檔案/目錄得到File對象

  • 示範

    File類的構造方法

    1. File file = new File(“E:\20151020\day02\day02總結.java”) ;

    2. File file2 = new File(“E:\20151020\day02” , “day02總結.java”) ;

    3. File file3 = new File(“E:\20151020\day02”) ;

    File file4 = new File(file3 , “day02總結.java”) ;

8.2 File類的建立功能

  • 建立功能

    public boolean createNewFile():建立一個新的檔案 如果存在這樣的檔案,就不建立了

    public boolean mkdir():建立檔案夾 如果存在這樣的檔案夾,就不建立了 注意這個方法隻能建立單層目錄 如果建立多層目錄得一層一層建立

    public boolean mkdirs():建立檔案夾,如果父檔案夾不存在,會幫你建立出來 可以建立多層目錄 當然也可以建立單層目錄

  • 示範:File類的建立功能
public class Test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\Users\\ShenMouMou\\Desktop\\b.txt");
        //建立檔案,第一次建立成功傳回true,重複建立傳回false
        boolean b = file.createNewFile();
        System.out.println(b);
        System.out.println("=========================");
        File file1 = new File("C:\\Users\\ShenMouMou\\Desktop\\hehe");
        //建立目錄 ,第一次建立成功傳回true,重複建立傳回false
        boolean b1 = file1.mkdir();  //建立單級目錄
        System.out.println(b1);

        System.out.println("===============================");

        File file2 = new File("C:\\Users\\ShenMouMou\\Desktop\\haha\\aaa\\bbb");
        boolean mkdir = file2.mkdirs(); //可以建立單級或多級目錄,記這個
        System.out.println(mkdir);
    }
}
           

**注意事項:**如果你建立檔案或者檔案夾忘了寫盤符路徑,那麼,預設在項目路徑下。

  • 相對路徑:沒有帶盤符的路徑
  • 絕對路徑:帶有盤符的路徑

8.3 File類的删除功能

  • public boolean delete():删除檔案或者檔案夾

**注意:**删除檔案夾時 這個檔案夾是空檔案夾 如果這個檔案夾裡面有檔案,則不能删除

  • 示範
public class Test {
    public static void main(String[] args) {

        File file = new File("C:\\Users\\ShenMouMou\\Desktop\\b.txt");
        //第一次删除成功傳回true,删除不存在的檔案傳回false
        boolean b = file.delete();
        System.out.println(b);

        File file2 = new File("C:\\Users\\ShenMouMou\\Desktop\\hehe");
        //delete()隻能删除空目錄,非空目錄無法直接删除
        boolean delete = file2.delete();
        System.out.println(delete);

        File file3 = new File("C:\\Users\\ShenMouMou\\Desktop\\haha");
        boolean delete2 = file3.delete();
        System.out.println(delete2);
    }
}
           

**注意事項:**Java中的删除不走資源回收筒。要删除一個檔案夾,請注意該檔案夾内不能包含檔案或者檔案夾

8.4 File類的重命名功能

  • public boolean renameTo(File dest):

    把檔案重命名為指定的檔案路徑

  • 示範:File類的重命名功能
public class Test {
    public static void main(String[] args) {

        //file.renameTo(newFile);
        //A檔案和B檔案的父路徑一緻,就是重名
        //A檔案和B檔案的父路徑不一緻,就是剪切 把A檔案剪切到B檔案的路徑下
        //A檔案.renameTo(B檔案);
        File file = new File("C:\\Users\\ShenMouMou\\Desktop\\aaa.txt");
        File newFile = new File("D:\\bbb.txt");
        boolean b = file.renameTo(newFile);
        System.out.println(b);

        System.out.println("=================================");
    }
}
           

注意事項:

如果路徑名相同,就是改名。

如果路徑名不同,就是改名并剪切。

8.5 File類的判斷功能

  • public boolean isDirectory(): 判斷是否是目錄
  • public boolean isFile(): 判斷是否是檔案
  • public boolean exists(): 判斷是否存在
  • public boolean canRead(): 判斷是否可讀
  • public boolean canWrite(): 判斷是否可寫
  • public boolean isHidden(): 判斷是否隐藏
  • public boolean isAbsolute(); 判斷是否使用的是絕對路徑

8.6 File類的擷取功能

  • public String getAbsolutePath():

    擷取絕對路徑

  • public String getPath():

    擷取相對路徑

  • public String getParent()

    傳回此抽象路徑名父目錄的路徑名字元串;如果此路徑名沒有指定父目錄,則傳回 null

  • public File getParentFile()

    傳回此抽象路徑名父目錄的抽象路徑名;如果此路徑名沒有指定父目錄,則傳回 null

  • public long getTotalSpace()

    傳回此抽象路徑名指定的分區大小。 傳回總容量 機關位元組

  • public long getFreeSpace()

    傳回此抽象路徑名指定的分區中未配置設定的位元組數。傳回剩餘容量 機關位元組

  • public String getName(): 擷取名稱
  • public long length(): 擷取長度,位元組數
  • public long lastModified():擷取最後一次的修改時間,毫秒值
  • public String[] list(): 擷取指定目錄下的所有檔案或者檔案夾的名稱數組
  • public File[] listFiles(): 擷取指定目錄下的所有檔案或者檔案夾的File數組

9.檔案名稱過濾器的概述及使用

  • 檔案名稱過濾器的概述

    public String[] list(FilenameFilter filter)

    public File[] listFiles(FilenameFilter filter)

練習:輸出指定目錄下指定字尾的檔案名

  • 需求:判斷E盤目錄下是否有字尾名為.jpg的檔案,如果有,就輸出該檔案名稱
  • 分析:

    a.把E:\demo這個路徑封裝成一個File對象

    b.擷取該路徑下所有的檔案或者檔案夾對應的File數組

    c.周遊這個數組,進行判斷

public class MyTest3 {
    public static void main(String[] args) {
    
        File file = new File("C:\\Users\\ShenMouMou\\Desktop\\demo");

        File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                // System.out.println(dir + "===" + name);
                File file1 = new File(dir, name);
                if (file1.isFile() && file1.getName().endsWith(".png")) {
                    return true;
                }
                return false; //傳回true 就把把檔案過濾到數組中,傳回false就不會過濾到數組中
            }
        });

        System.out.println(Arrays.toString(files));
    }
}