今日內容
- 異常
- File類
- IO(字節流) input : 輸入 --> 讀取 Output : 輸出 --> 寫出
01. 異常的概述和繼承體系
- 異常的概念:
異常:異常指的就是不正常
簡單理解就是我們程序所發生的錯誤。
例如:當出現異常的運算條件時,拋出此異常。例如,一個整數“除以零”時,拋出此類的一個實例。
- 常見的異常有:
ArrayIndexOutofboundsException
StringIndexOutofboundsException
ConcurrentModificationException
ClassCastException
NoSuchElementException
- 異常的體系的介紹:
Throwable 類是 Java 語言中所有錯誤或異常的超類。
Error 是 Throwable 的子類,用於指示合理的應用程序不應該試圖捕獲的嚴重問題。
也就是說針對程序發生了Error的情況,Java程序本身是無能爲力的,比如說:硬件層面的問題,內存不足等。
所以,針對Error的問題我們不處理。
Exception 類及其子類是 Throwable 的一種形式,它指出了合理的應用程序想要捕獲的條件。
也就是說針對程序發生了Exception的情況,是我們需要處理的問題。
- Exception的分類:
- RuntimeException: 運行時異常: 編譯通過了,運行時出現的錯誤
如果出現的運行時異常,就是我們程序員自身所發生的錯誤,是需要回頭修改源代碼的
int[] arr = null;
System.out.println(arr[0]);
2. !RuntimeException:
編譯時異常: 編譯器在編譯的過程中,檢測到某段代碼可能會發生怎樣的問題
這時候需要我們程序員對代碼進行異常的【預】處理,否則編譯是一直失敗的
FileReader fr = new FileReader("D:\\abc.txt");
注意:語法錯誤不是編譯時異常
02. JVM針對異常的默認處理方式
- 異常有哪幾種處理方式?
- jvm默認是如何處理異常的?
總結:
1. 異常分類兩種處理方式:
A. 問題很小,自己可以處理
try..catch
B. 問題很大,自己處理不了
【拋給上一級】
2. jvm默認選擇拋出異常的方式, 拋給調用者.
問題拋給main方法, 主方法的調用者是jvm, jvm接收到異常之後, 就將異常信息輸出在了控制檯.
並且強制的結束程序運行。
03. 異常處理方案try…catch
- 什麼情況下使用try..catch處理異常的方式
總結:
1. 當發現問題可以自己解決的時候, 使用try..catch進行處理
處理後,不會影響到後續代碼的繼續執行。
格式:
try {
需要包裹的是,有可能產生問題得代碼
} catch(要抓捕的異常) {
異常的處理方式
}
try...catch的執行順序:
首先會執行try語句中的代碼, 看被try包裹的代碼是否產生異常
有 : 異常被catch進行捕獲, 然後走catch語句中的代碼
沒有 : 程序繼續向下執行
好處: 使用try..catch語句自己將問題處理掉之後, 不會影響到後續代碼的執行
注意: 如果try語句中的代碼沒有發生異常, 那麼catch語句將不會執行.
catch中只能捕獲()中聲明的異常, 如果想要捕獲所有的異常, 可以寫成父類 Exception
alt + shift + z --> try..catch
如果catch捕獲的是多個異常, 那麼大的異常需要放在最下面!!!
練習:
需求: 編寫一段代碼, 要求代碼中會產生索引越界異常
並使用try...catch進行處理
分析:
第一步:定義數組
第二步:在打印語句中訪問不存在的索引
第三步:將可能發生問題的代碼用try包裹
第四步:catch中捕獲IndexOutOfBoundsException
第五步:對異常進行處理,並用printStackTrace打印出異常信息
異常對象的三個常用方法:
toString() : 簡短描述
getMessage() : 返回錯誤信息
printStackTrace() : 返回錯誤的完整信息(錯誤的行數, 錯誤的異常, 錯誤的原因) ***
04. 編譯時異常和運行時異常的區別
- 編譯時異常
- 運行時異常
總結:
1. 編譯時異常指的是編譯過程中, 編譯器檢測到某段代碼可能會出現怎樣的問題(文件找不到異常)(日期字符串輸入錯誤)
我們必須對該問題進行【預】處理,否則編譯是不能通過的。
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.parse("2019年3月15日");
}
2. 編譯通過了,運行時出現的錯誤
05. 異常處理方案throws
- 什麼情況下需要將異常拋出?
- 案例演示: setAge賦值錯誤.
總結:
1. 發現出現的問題,自己沒有一個合理的解決方案,就需要將錯誤拋給上級
代碼:
public void setAge(int age) throws Exception {
/*
* 假如我們是Person類的編寫者,在編寫方法的時候,不清楚調用者傳入的是正確的還是錯誤的參數
*
* 如果是錯誤的,需要讓調用者明白自己出錯了
*
* 解決方案:將程序強制終止,並將錯誤信息輸出在控制檯
*
* throw : 用於拋出真正的異常對象
*
* throws :僅僅是對方法進行一個聲明, 告知調用者,此方法存在異常,調用時需要處理
*/
if(age >= 0 && age <= 200){
this.age = age;
}else{
throw new Exception("您的年齡非法了!");
}
}
思路:
1. 如何拋出異常?
throw new 異常對象("錯誤信息");
2. 拋出異常對象之後呢?
需要在方法上進行throws聲明,告知調用者此方法存在異常
3. 調用者需要注意什麼?
明確該方法存在異常, 需要對異常進行處理
結論: throw throws的區別是什麼?
throw : 用於真正的拋出異常對象
throws : 僅僅是對方法進行聲明,告知調用者此方法存在異常
注意:
如果拋出的異常是RuntimeException的話, 那麼就不需要throws的聲明.
06. File類的概述和構造方法
-
A:File類的概述和作用
- a: File的概念
- File類是文件和目錄路徑名的抽象表示形式
- Java中把文件或者目錄(文件夾)都封裝成File對象
總結:
在java當中, 使用file類來表示(文件路徑)或者是(文件夾路徑)
思路: 如果今後要操作硬盤中的某一個文件或者是文件夾的話, 那麼首先要考慮將要操作數據的路徑封裝成file對象.
- a: File的概念
-
B: File類的常用構造方法:
- File(String pathname) :將一個字符串路徑封裝成File對象 ****
- File(String parent,String child):傳入一個父級路徑和子級路徑
- File(File parent,String child):傳入一個File類型的父級路徑和子級路徑 ****
07. File類的創建功能
- boolean createNewFile():指定路徑不存在該文件時時創建文件,返回true,否則返回false
- boolean mkdir():當指定的單級文件夾不存在時創建文件夾並返回true,否則返回false ****
- boolean mkdirs():當指定的多級文件夾某一級文件夾不存在時,創建多級文件夾並返回true,否則返回false ****
08. File類的刪除功能
- boolean delete():刪除文件或者刪除單級文件夾 ****
注意: delete方法在刪除文件的時候沒有問題
delete方法在刪除文件夾
1. 單級文件夾 ,並且該文件夾必須是一個空的文件夾
需求:鍵盤接受一個文件夾路徑,刪除該文件夾下所有的內容(遞歸)
總結:
相對路徑: 相對於當前項目Project下
絕對路徑: 從盤符的根目錄開始,一直只指向到具體的文件或文件夾
09. File類的判斷和獲取功能
判斷功能(重點)****
- boolean exists():判斷指定路徑的文件或文件夾是否存在
- boolean isDirectory():判斷當前的目錄是否存在
- boolean isFile():判斷當前路徑是否是一個文件
獲取功能
- String getAbsolutePath():獲取文件的絕對路徑,返回路徑的字符串 ****
- String getPath():獲取File對象中封裝的路徑
- String getName():獲取文件或文件夾的名稱 ****
案例演示
- 需求: 鍵盤錄入一個文件夾路徑
- 如果錄入的文件不存在給出提示
- 如果錄入的是一個文件,給出提示
- 直到錄入了正確的文件夾路徑爲止, 程序終止
10. IO流的概述和分類
- 什麼是IO流?
- IO流的分類有哪些?
總結:
1.
I : input -> 輸入 -> 讀取
O : output -> 輸出 -> 寫出
2.
流向分:
1. 輸入流 -> 讀取數據
2. 輸出流 -> 寫出數據
類型分:
字節流:
字節流可以稱之爲萬能流,因爲硬盤上任意一個文件都是以字節的形式存儲的
但是字節流在操作純文本文件的時候,有可能會出現一些亂碼的問題
字符流:
如果今後操作的數據是純文本文件,建議使用字符流,避免亂碼的問題。
注意: IO流的抽象父類有哪些?
字節流:
輸入流抽象父類: IntpuStream
輸出流抽象方法: OuputStream
小竅門:只要遇到類名是以xxxxStream爲結尾的,就說明是一個字節流
字符流:
輸入流抽象父類: Reader
輸出流抽象父類: Writer
小竅門:只要遇到類名是以Reader\Writer爲結尾的,就說明是一個字符流
11. FileOutputStream寫數據
- 構造方法
- 寫出數據使用的成員方法
總結:
1.FileOutputStream(String name) : 創建字節輸出流對象,將要關聯的文件以字符串給出
FileOutputStream(File file) : 創建字節輸出流對象,將要關聯的文件以File對象形式給出
2.
write(int b)
代碼:
IO流操作的基本步驟
// 1. 創建字節輸出流對象
// 輸出流關聯文件, 如果文件不存在, 則自動創建
FileOutputStream fos = new FileOutputStream("a1.txt");
// 2. 調用輸出流對象的方法寫出數據
String s = "你可能說不出哪裏好, 但我就是想看你洗澡";
fos.write(s.getBytes());
// 3. 關閉流釋放資源!
fos.close();
- 轉ppt練習
12. FileOutputStream寫數據的三種方式.
- public void write(int b):一次寫一個字節
- public void write(byte[] b):一次寫一個字節數組
- public void write(byte[] b,int off,int len):一次寫一個字節數組的一部分
13. FileOutputStream如何實現換行和追加寫數據
- 如何實現數據的換行寫入?
- 如何實現數據的尾部追加動作?
總結:
1. 通過write方法將\r\n寫出去。-123、
windowns : \r\n
Linux : \n
Mac : \r
BufferedWriter -> newLine() -> 具有跨平臺性
2. FileOutputStream(File file, boolean append)
FileOutputStream(String name, boolean append)
在構造方法的參數中, 傳入true, 開啓尾部追加
14. FileOutputStream寫數據加入異常處理
FileOutputStream fos = null;
try {
// FileOutputStream fos = new FileOutputStream("d.txt");
// fos = new FileOutputStream("z:\\d.txt");
fos = new FileOutputStream("d.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
// 釋放資源
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
15. FileInputStream讀數據方式1一次讀取一個字節
- 構造方法: FileInputStream(String name)
- FileInputStream是通過哪個方法讀取數據的? 文件的末尾結束標記爲?
* int read();
* -1
int i;
while((i = fis.read()) != -1){
}
- 輸入和輸出的注意事項:
- 輸出流操作文件, 如果文件不存在的話, 程序將會自動創建出一個
- 輸入流讀取文件, 如果文件不存在, 則會拋出FileNotFoundException
只能操的是文件,文件夾不能操作(拒絕訪問)
- 轉ppt練習
16. FileInputStream讀數據方式2一次讀取一個字節數組.
- 單個字節讀取效率如何?
- 一次讀取一個字節數組的注意問題:
總結:
1. 效率低下
2. 一次如果讀取一個字節輸出,在轉換的過程中,如果沒有做好處理,就會出現數據的殘留現象。
如何解決?
// 1. 創建輸入流對象關聯數據源
FileInputStream fis = new FileInputStream("aaa\\aaa.txt");
// 2. 定義字節數組容器, 爲了提高讀取的效率
byte[] bys = new byte[2];
// 3. 定義臨時變量, 用於不斷的記錄read方法返回的有效字節個數
int len = 0;
// 4. 使用while循環不斷的讀取, 將read方法的返回值賦值給len
while((len = fis.read(bys)) != -1){
System.out.print(new String(bys, 0, len));
}
fis.close();
依賴的方法:
String(byte[] bytes, int offset, int length) -> 構造方法
將傳入的字節數組的一部分, 轉換成字符串
bytes : 數據源
offset : 起始的索引位置
length : 轉換的個數
17. 字節流練習之複製文本文件.
- 案例演示
- 需求
拷貝文本文件
分析:
第一步: 創建輸入輸出流對象關聯數據源和數據目的
第二步: 定義字節數組,爲了提高效率
第三步: 將數據通過while循環不斷讀取到字節數組中
第四步: 將數據從字節數組中取出並寫出
第五步: 釋放資源
// 1. 創建輸入流對象關聯數據源
FileInputStream fis = new FileInputStream("窗裏窗外.txt");
// 2. 創建輸出流對象關聯數據目的
FileOutputStream fos = new FileOutputStream("copyText.txt");
// 3. 使用java程序讀取數據源中的數據, 將讀取到的數據寫出到目標文件中
byte[] bys = new byte[2048];
int len = 0;
while((len = fis.read(bys)) != -1){
fos.write(bys, 0, len);
}
// 4. 關閉流釋放資源
fis.close();
fos.close();
18. 字節流練習之複製圖片
- 案例演示
- 5分鐘時間練習