Java基礎-20(01)總結,遞迴,IO流
阿新 • • 發佈:2022-05-04
(1)方法定義中呼叫方法本身的現象
舉例:老和尚給小和尚講故事,我們學程式設計
(2)遞迴的注意事項;
A:要有出口,否則就是死遞迴
B:次數不能過多,否則記憶體溢位
C:構造方法不能遞迴使用
package cn.itcast_01; /* * 遞迴:方法定義中呼叫方法本身的現象 * * 方法的巢狀呼叫,這不是遞迴。 * Math.max(Math.max(a,b),c); * * public void show(int n) { * if(n <= 0) { * System.exit(0); * } * System.out.println(n); * show(--n); * } * * 注意事項: * A:遞迴一定要有出口,否則就是死遞迴 * B:遞迴的次數不能太多,否則就記憶體溢位 * C:構造方法不能遞迴使用 * * 舉例: * A:從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是: * 從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是: * 從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是: * 從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是: * ... * 廟掛了,或者山崩了 * B:學程式設計 -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費 * 學程式設計 -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費 * 學程式設計 -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費 * 學程式設計 -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費 * ... * 娶不到媳婦或者生不了娃娃 */ public class DiGuiDemo { // public DiGuiDemo() { // DiGuiDemo(); // } }
(3)遞迴的案例:
A:遞迴求階乘
package cn.itcast_02; /* * 需求:請用程式碼實現求5的階乘。 * 下面的知識要知道: * 5! = 1*2*3*4*5 * 5! = 5*4! * * 有幾種方案實現呢? * A:迴圈實現 * B:遞迴實現 * a:做遞迴要寫一個方法 * b:出口條件 * c:規律 */ public class DiGuiDemo { public static void main(String[] args) { int jc = 1; for (int x = 2; x <= 5; x++) { jc *= x; } System.out.println("5的階乘是:" + jc); System.out.println("5的階乘是:"+jieCheng(5)); } /* * 做遞迴要寫一個方法: * 返回值型別:int * 引數列表:int n * 出口條件: * if(n == 1) {return 1;} * 規律: * if(n != 1) {return n*方法名(n-1);} */ public static int jieCheng(int n){ if(n==1){ return 1; }else { return n*jieCheng(n-1); } } }
B:兔子發展問題 (斐波那契數列)
package cn.itcast_02; /* * 有一對兔子,從出生後第3個月起每個月都生一對兔子,小兔子長到第三個月後每個月又生一對兔子,假如兔子都不死,問第二十個月的兔子對數為多少? * 分析:我們要想辦法找規律 * 兔子對數 * 第一個月: 1 * 第二個月: 1 * 第三個月: 2 * 第四個月: 3 * 第五個月: 5 * 第六個月: 8 * ... * * 由此可見兔子物件的資料是: * 1,1,2,3,5,8... * 規則: * A:從第三項開始,每一項是前兩項之和 * B:而且說明前兩項是已知的 * * 如何實現這個程式呢? * A:陣列實現 * B:變數的變化實現 * C:遞迴實現 * * 假如相鄰的兩個月的兔子對數是a,b * 第一個相鄰的資料:a=1,b=1 * 第二個相鄰的資料:a=1,b=2 * 第三個相鄰的資料:a=2,b=3 * 第四個相鄰的資料:a=3,b=5 * 看到了:下一次的a是以前的b,下一次是以前的a+b */ public class DiGuiDemo2 { public static void main(String[] args) { // 定義一個數組 int[] arr = new int[20]; arr[0] = 1; arr[1] = 1; // arr[2] = arr[0] + arr[1]; // arr[3] = arr[1] + arr[2]; // ... for (int x = 2; x < arr.length; x++) { arr[x] = arr[x - 2] + arr[x - 1]; } System.out.println(arr[19]);// 6765 System.out.println("----------------"); int a = 1; int b = 1; for (int x = 0; x < 18; x++) { // 臨時變數儲存上一次的a int temp = a; a = b; b = temp + b; } System.out.println(b); System.out.println("----------------"); System.out.println(fib(20)); } /* * 方法: 返回值型別:int 引數列表:int n 出口條件: 第一個月是1,第二個月是1 規律: 從第三個月開始,每一個月是前兩個月之和 */ public static int fib(int n) { if (n == 1 || n == 2) { return 1; } else { return fib(n - 1) + fib(n - 2); } } }
C:遞迴輸出指定目錄下所有指定字尾名的檔案絕對路徑
package cn.itcast_03;
import java.io.File;
/*
* 需求:請大家把E:JavaSE目錄下所有的java結尾的檔案的絕對路徑給輸出在控制檯。
*
* 分析:
* A:封裝目錄
* B:獲取該目錄下所有的檔案或者資料夾的File陣列
* C:遍歷該File陣列,得到每一個File物件
* D:判斷該File物件是否是資料夾
* 是:回到B
* 否:繼續判斷是否以.java結尾
* 是:就輸出該檔案的絕對路徑
* 否:不搭理它
*/
public class FilePathDemo {
public static void main(String[] args) {
// 封裝目錄
File srcFolder = new File("E:\JavaSE");
// 遞迴功能實現
getAllJavaFilePaths(srcFolder);
}
private static void getAllJavaFilePaths(File srcFolder) {
// 獲取該目錄下所有的檔案或者資料夾的File陣列
File[] fileArray = srcFolder.listFiles();
// 遍歷該File陣列,得到每一個File物件
for (File file : fileArray) {
// 判斷該File物件是否是資料夾
if (file.isDirectory()) {
getAllJavaFilePaths(file);
} else {
// 繼續判斷是否以.java結尾
if (file.getName().endsWith(".java")) {
// 就輸出該檔案的絕對路徑
System.out.println(file.getAbsolutePath());
}
}
}
}
}
D:遞迴刪除帶內容的目錄(小心使用)
package cn.itcast_03;
import java.io.File;
/*
* 需求:遞迴刪除帶內容的目錄
*
* 目錄我已經給定:demo
*
* 分析:
* A:封裝目錄
* B:獲取該目錄下的所有檔案或者資料夾的File陣列
* C:遍歷該File陣列,得到每一個File物件
* D:判斷該File物件是否是資料夾
* 是:回到B
* 否:就刪除
*/
public class FileDeleteDemo {
public static void main(String[] args) {
// 封裝目錄
File srcFolder = new File("demo");
// 遞迴實現
deleteFolder(srcFolder);
}
private static void deleteFolder(File srcFolder) {
// 獲取該目錄下的所有檔案或者資料夾的File陣列
File[] fileArray = srcFolder.listFiles();
if (fileArray != null) {
// 遍歷該File陣列,得到每一個File物件
for (File file : fileArray) {
// 判斷該File物件是否是資料夾
if (file.isDirectory()) {
deleteFolder(file);
} else {
System.out.println(file.getName() + "---" + file.delete());
}
}
System.out
.println(srcFolder.getName() + "---" + srcFolder.delete());
}
}
}
2:IO流(掌握)
(1)IO用於在裝置間進行資料傳輸的操作
(2)分類:
A:流向
輸入流 讀取資料
輸出流 寫出資料
B:資料型別
位元組流
位元組輸入流
位元組輸出流
字元流
字元輸入流
字元輸出流
注意:
a:如果我們沒有明確說明按照什麼分,預設按照資料型別分。
b:除非檔案用windows自帶的記事本開啟我們能夠讀懂,才採用字元流,否則建議使用位元組流。
(3)FileOutputStream寫出資料
A:操作步驟
a:建立位元組輸出流物件
b:呼叫write()方法
c:釋放資源
B:程式碼體現:
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();
C:要注意的問題?
a:建立位元組輸出流物件做了幾件事情?
b:為什麼要close()?
package cn.itcast_01;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* IO流的分類:
* 流向:
* 輸入流 讀取資料
* 輸出流 寫出資料
* 資料型別:
* 位元組流
* 位元組輸入流 讀取資料 InputStream
* 位元組輸出流 寫出資料 OutputStream
* 字元流
* 字元輸入流 讀取資料 Reader
* 字元輸出流 寫出資料 Writer
*
* 注意:一般我們在探討IO流的時候,如果沒有明確說明按哪種分類來說,預設情況下是按照資料型別來分的。
*
* 需求:我要往一個文字檔案中輸入一句話:"hello,io"
*
* 分析:
* A:這個操作最好是採用字元流來做,但是呢,字元流是在位元組流之後才出現的,所以,今天我先講解位元組流如何操作。
* B:由於我是要往檔案中寫一句話,所以我們要採用位元組輸出流。
*
* 通過上面的分析後我們知道要使用:OutputStream
* 但是通過檢視API,我們發現該流物件是一個抽象類,不能例項化。
* 所以,我們要找一個具體的子類。
* 而我們要找的子類是什麼名字的呢?這個時候,很簡單,我們回想一下,我們是不是要往檔案中寫東西。
* 檔案是哪個單詞:File
* 然後用的是位元組輸出流,聯起來就是:FileOutputStream
* 注意:每種基類的子類都是以父類名作為字尾名。
* XxxOutputStream
* XxxInputStream
* XxxReader
* XxxWriter
* 檢視FileOutputStream的構造方法:
* FileOutputStream(File file)
* FileOutputStream(String name)
*
* 位元組輸出流操作步驟:
* A:建立位元組輸出流物件
* B:寫資料
* C:釋放資源
*/
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 建立位元組輸出流物件
// FileOutputStream(File file)
// File file = new File("fos.txt");
// FileOutputStream fos = new FileOutputStream(file);
// FileOutputStream(String name)
FileOutputStream fos = new FileOutputStream("fos.txt");
/*
* 建立位元組輸出流物件了做了幾件事情:
* A:呼叫系統功能去建立檔案
* B:建立fos物件
* C:把fos物件指向這個檔案
*/
//寫資料
fos.write("hello,IO".getBytes());
fos.write("java".getBytes());
//釋放資源
//關閉此檔案輸出流並釋放與此流有關的所有系統資源。
fos.close();
/*
* 為什麼一定要close()呢?
* A:讓流物件變成垃圾,這樣就可以被垃圾回收器回收了
* B:通知系統去釋放跟該檔案相關的資源
*/
//java.io.IOException: Stream Closed
//fos.write("java".getBytes());
}
}
c:如何實現資料的換行?
d:如何實現資料的追加寫入?
package cn.itcast_01;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 如何實現資料的換行?
* 為什麼現在沒有換行呢?因為你值寫了位元組資料,並沒有寫入換行符號。
* 如何實現呢?寫入換行符號即可唄。
* 剛才我們看到了有寫文字檔案開啟是可以的,通過windows自帶的那個不行,為什麼呢?
* 因為不同的系統針對不同的換行符號識別是不一樣的?
* windows:rn
* linux:n
* Mac:r
* 而一些常見的個高階記事本,是可以識別任意換行符號的。
*
* 如何實現資料的追加寫入?
* 用構造方法帶第二個引數是true的情況即可
*/
public class FileOutputStreamDemo3 {
public static void main(String[] args) throws IOException {
// 建立位元組輸出流物件
// FileOutputStream fos = new FileOutputStream("fos3.txt");
// 建立一個向具有指定 name 的檔案中寫入資料的輸出檔案流。如果第二個引數為 true,則將位元組寫入檔案末尾處,而不是寫入檔案開始處。
FileOutputStream fos = new FileOutputStream("fos3.txt", true);
// 寫資料
for (int x = 0; x < 10; x++) {
fos.write(("hello" + x).getBytes());
fos.write("rn".getBytes());
}
// 釋放資源
fos.close();
}
}
e:異常處理的位元組輸出流操作
package cn.itcast_01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 加入異常處理的位元組輸出流操作
*/
public class FileOutputStreamDemo4 {
public static void main(String[] args) {
// 分開做異常處理
// FileOutputStream fos = null;
// try {
// fos = new FileOutputStream("fos4.txt");
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
//
// try {
// fos.write("java".getBytes());
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// try {
// fos.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 一起做異常處理
// try {
// FileOutputStream fos = new FileOutputStream("fos4.txt");
// fos.write("java".getBytes());
// fos.close();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 改進版
// 為了在finally裡面能夠看到該物件就必須定義到外面,為了訪問不出問題,還必須給初始化值
FileOutputStream fos = null;
try {
// fos = new FileOutputStream("z:\fos4.txt");
fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 如果fos不是null,才需要close()
if (fos != null) {
// 為了保證close()一定會執行,就放到這裡了
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}