遞歸、字節流、文件復制_DAY20
1:遞歸(理解)
(1)方法定義中調用方法本身的現象。
(2)遞歸註意事項:
A:要有出口,否則就是死遞歸。
B:次數不能太多,否則內存溢出。
特殊事項:構造方法不能遞歸定義。
例子:cn.itcast.demo
package cn.itcast; /* * 遞歸算法: * 自己調用自己。 * 方法內定義:調用到什麽程度,就不調用自己了。即遞歸出口。 */ public class Demo { public static void main(String[] args) { method(View Code5); } public static void method(int flag){ System.out.println("我是一個遞歸方法調用前的代碼"+flag); if(flag>0) { flag--; method(flag); System.out.println("我是一個遞歸方法調用後的代碼"+flag); } else { System.out.println("遞歸出口出來了!");return; } } }
(3)案例:(面試可能見到)
A:遞歸求1到10的和 例子:cn.itcast.Test
package cn.itcast; /* * 遞歸:將復雜問題分解,即復雜問題簡單化。 * 使用遞歸求1-10的和。 * 10 + 1-9的和 * 9 + 1-8的和 * 8+ 1-7的和 * ... * 3+ 1-2和 * 2+ 1的和 * 1 返回1 */ publicView Codeclass Test { public static void main(String[] args) { System.out.println(getSum(3)); } //獲取1到指定數字的和 public static int getSum(int number) { //遞歸出口:如果加到1了,則返回1。 if(number==1) { return 1; //如果不是1,就使用這個數,加上:1——比它小1的數的和。 }else { int nextNumber = number-1; return number + getSum(nextNumber); } } }
B:遞歸求階乘 例子:cn.itcast.Test0
/** * 階乘 * 10 * 9-1 * 9 * 8-1 * 8 * 7-1 * ... * 2 * 1 * 1 return 1; */ public class Factorial { public static void main(String[] args) { int max=4; int factorial=method(max); System.out.println(factorial); } public static int method(int max) { int fatorial=max; if(max==1){ return max; }else { fatorial=max*method(max-1); max--; } return fatorial; } }View Code
C:遞歸求5的階乘 例子:cn.itcast.Test2
package cn.itcast; /* * 遞歸:將復雜問題分解,即復雜問題簡單化。 * 使用遞歸求5的階乘。 */ public class Test2 { public static void main(String[] args) { System.out.println(getSum(5)); } //獲取1到指定數字的積 public static int getSum(int number) { //遞歸出口:如果加到1了,則返回1。 if(number==1) { return 1; //如果不是1,就使用這個數,加上:1——比它小1的數的和。 }else { int nextNumber = number-1; return number * getSum(nextNumber); } } }View Code
D:遞歸求兔子問題(斐波那契數列) cn.itcast.Test4; n.itcast.Test3
package cn.itcast; /* * 使用遞歸計算斐波那契數列 * 結果: 1 1 2 3 5 8 13 21 34... * number:1 2 3 4 5 * 計算到第幾個數時,那個數是多少 */ public class Test3 { public static void main(String[] args) { System.out.println(method(7)); } //這個方法到底是幹什麽的?給我第幾個數,我給你返回這一個數的值。!!!! public static int method(int number) { //number:第幾個數 if(number == 1||number == 2) {//如果是前兩個數,就返回1 return 1; } else { int before = number-1; //得到前一個數是第幾個數 int beforeBefore = number-2; //得到前一個數的前一個數是第幾個數 return method(before) + method(beforeBefore); //拿到前一個數的值,拿到前一個數的前一個數的值,相加,得到這個數。 } } }View Code
package cn.itcast; /* * 一對兔子:每到第三個月,生一對兔子,之後每個月都生一對兔子。這一對小兔子,在第三個月時,生下一對兔子,之後每個月都生一對兔子。 * 註意: * 兔子,不生病,不死亡。 * 問某個月後,有多少對兔子? * 1 : 1 * A1 * 2 : 1 * A2 * 3 : 2 * A3 B1 * 4 : 3 * A3 C1 B2 * 5 : 5 * A3 D1 C2 B3 E1 * 6 : 8 * A3 F1 D2 C3 G1 B3 H1 E2 * 7 : 13 * A3 J1 F2 D3 K1 C3 L1 G2 B3 M1 H2 E3 N1 */ public class Test4 { public static void main(String[] args) { //使用斐波那契數列 } }View Code
E:遞歸遍歷目錄(帶內容的目錄) cn.itcast.Test5
package cn.itcast; import java.io.File; /* * 遞歸輸出指定目錄下所有java文件的絕對路徑 */ public class Test5 { public static void main(String[] args) { File file = new File("src"); method(file); } public static void method(File dir) { File[] listFiles = dir.listFiles(); for (File fileorDir : listFiles) { //如果是文件夾 if(fileorDir.isDirectory()) { System.out.println("dir:"+fileorDir.getName()); method(fileorDir); } else { //如果是文件 if(fileorDir.getName().endsWith(".java")) //判斷文件名是否以.java結尾 System.out.println(fileorDir.getAbsolutePath()); } } } }View Code
F:遞歸刪除目錄(帶內容的目錄) cn.itcast.Test6
package cn.itcast; import java.io.File; /* * 遞歸刪除指定文件夾 */ public class Test6 { public static void main(String[] args) { File dir = new File("a"); method(dir); } public static void method(File dir) { //先刪除內容 //返回該目錄下所有的文件及文件夾對象 File[] listFiles = dir.listFiles(); for (File fileorDir : listFiles) { if(fileorDir.isDirectory()) { //刪除這個文件夾 method(fileorDir); }else { //直接刪除這個文件 System.out.println(fileorDir.getName()); fileorDir.delete(); } } //刪除我自己 System.out.println(dir.getName()); dir.delete(); } }View Code
2:IO(掌握)
(1)IO就是在不同設備間傳遞數據。
(2)IO流分類:
A:流向
輸入流 讀取數據
輸出流 寫出數據
B:數據類型
字節流
字節輸入流 InputStream
文件字節輸入流:FileInputStream 例子:cn.itcast3.demo2
package cn.itcast3; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; /* * 文件字節輸入流:FileInputStream * 構造方法: * public FileInputStream(File file)throws FileNotFoundException。 * public FileInputStream(String name)throws FileNotFoundException。 * 主要方法: * public int read() throws IOException 一次讀取一個字節 * public int read(byte[] b) throws IOException 一次讀取一個字節數組 返回值為本次讀到的字節個數 */ public class Demo2 { public static void main(String[] args) throws IOException { method2(); } public static void method() throws FileNotFoundException, IOException { //創建流對象 FileInputStream fis = new FileInputStream(new File("b.txt")); //讀取輸入 // int myByte = fis.read(); // System.out.println(myByte); // int myByte2 = fis.read(); // System.out.println(myByte2); // int myByte3 = fis.read(); // System.out.println(myByte3); // int myByte4 = fis.read(); // System.out.println(myByte4); // int myByte5 = fis.read(); // System.out.println(myByte5); int c; while((c=fis.read())!=-1) { System.out.println(c); } //關閉資源 fis.close(); } public static void method2() throws FileNotFoundException, IOException { //創建流對象 FileInputStream fis = new FileInputStream(new File("b.txt")); //b.txt內容: javav\r\n //讀取輸入 byte[] bytes = new byte[3]; // int len = fis.read(bytes); //{j,a,v} // System.out.println(len); // System.out.println(Arrays.toString(bytes)); // int len2 = fis.read(bytes); //{a,v,\r} // System.out.println(len2); // System.out.println(Arrays.toString(bytes)); // int len3 = fis.read(bytes); //{\n,v,\r} //v,\r重復讀取了 // System.out.println(len3); // System.out.println(Arrays.toString(bytes)); int len; while((len=fis.read(bytes))!=-1) { // System.out.println(Arrays.toString(bytes)); System.out.println(new String(bytes, 0, len)); } //關閉資源 fis.close(); } }View Code
字節輸出流 OutputStream
文件字節輸出流:FileOutputStream 例子:cn.itcast3.demo
package cn.itcast3; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; /* * 字節輸出流:OutputStream * 00000000 00000000 00000000 0000 1111 15 * * 文件字節輸出流:FileOutputStream * 構造方法: * public FileOutputStream(File file)throws FileNotFoundException 寫出是覆蓋操作,不是追加。 * public FileOutputStream(String name)throws FileNotFoundException 寫出是覆蓋操作,不是追加。 * public FileOutputStream(File file,boolean append)throws FileNotFoundException 布爾值為true,寫出追加操作。 * public FileOutputStream(String name,boolean append)throws FileNotFoundException 布爾值為true,寫出追加操作。 * 主要方法: * public void write(int b) throws IOException 寫出一個字節 * public void write(byte[] b) throws IOException 寫出一個字節數組 * * 註意: * 1:使用(File file)與(String name)參數的構造方法,寫出是覆蓋操作。 * 使用(File file,boolean append)與(String name,boolean append)參數的構造方法,寫出是追加操作。 * 2:使用一次一個字節的方式,無法直接輸出中文。可以使用一次一個字節數組的方式。 * 3:如果寫出目標的這個文件不存在,則直接創建一個文件,再寫出。 */ public class Demo { public static void main(String[] args) throws FileNotFoundException,IOException { method3(); } //一次輸出一個字節。 public static void method() throws FileNotFoundException,IOException { //1創建流對象 FileOutputStream fos = null; try { File file = new File("b.txt"); fos = new FileOutputStream(file); //2寫出內容 fos.write(-42); fos.write(-48); fos.write(‘9‘); fos.write(‘7‘); fos.write(‘中‘); } catch (Exception e) { e.printStackTrace(); } finally { if(fos!=null) { //3關閉資源 fos.close(); } } } //一次輸出一個字節數組。 public static void method2() throws FileNotFoundException,IOException { //1創建流對象 FileOutputStream fos = new FileOutputStream("b.txt"); //2準備寫出的數據 // byte[] data = new byte[]{97,98,99,100}; //方式一 String sData = "java中國"; //方式二 byte[] data = sData.getBytes(); System.out.println(Arrays.toString(data)); //3寫出內容 fos.write(data); //4關閉資源 fos.close(); } //一次輸出一個字節數組。追加 public static void method3() throws FileNotFoundException,IOException { //1創建流對象 FileOutputStream fos = new FileOutputStream("b.txt",true); //2準備寫出的數據 // byte[] data = new byte[]{97,98,99,100}; String sData = "java中國"; byte[] data = sData.getBytes(); System.out.println(Arrays.toString(data)); //3寫出內容 fos.write(data); //4關閉資源 fos.close(); } }View Code
例子:文件的復制 :cn.itcast3.demo3
package cn.itcast3; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* * 文件復制: * 方式一:一次一個字節的復制。 * 方式二:一次一個字節數組的復制。 / */ public class Demo3 { public static void main(String[] args) throws IOException { method2(); } //一次一個字節: public static void method() throws FileNotFoundException, IOException { //創建流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //讀 int c; while((c=fis.read())!=-1) { //一次讀一個字節 //寫 fos.write(c); } //關閉流 fos.close(); fis.close(); } //一次一個字節數組: public static void method2() throws FileNotFoundException, IOException { //創建流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //讀 //定義字節數組用來接收讀取到的字節們 byte[] bytes = new byte[4]; //定義變量,記錄本次讀取到的字節個數 int len; //循環讀取文件內容 while((len = fis.read(bytes))!=-1) { //只要讀到信息就進入循環體 //寫 //一次寫入長度為4的數組內容 fos.write(bytes,0,len); } //關閉流 fos.close(); fis.close(); } }View Code
高效字節流:將原有IO流進行包裝,使其效率更高。
高效字節輸出流:BufferedOutputStream
高效字節輸入流:BufferedInputStream
例子:cn.itcast3.demo4
package cn.itcast3; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* * 高效字節流: * BufferedInputStream * BufferedOutputStream * * 構造方法:均要一個對應的流對象 * public BufferedOutputStream(OutputStream out)創建一個新的緩沖輸出流,以將數據寫入指定的底層輸出流。 * public BufferedInputStream(InputStream in)創建一個 BufferedInputStream 並保存其參數,即輸入流 in,以便將來使用。創建一個內部緩沖區 * 數組並將其存儲在 buf 中。 * */ public class Demo4 { public static void main(String[] args) throws IOException { long currentTimeMillis = System.currentTimeMillis(); //創建輸入流對象 FileInputStream fis = new FileInputStream("b.txt"); BufferedInputStream bis = new BufferedInputStream(fis); //創建輸出流對象 FileOutputStream fos = new FileOutputStream("b2.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); //讀入 byte[] bytes = new byte[2]; int len; while((len=bis.read(bytes))!=-1) { //寫出 bos.write(bytes, 0, len); bos.flush(); //刷新此緩沖的輸出流。這迫使所有緩沖的輸出字節被寫出到底層輸出流中。 } //關閉流 bos.close(); bis.close(); long currentTimeMillis2 = System.currentTimeMillis(); System.out.println(currentTimeMillis2-currentTimeMillis); } }View Code
字符流
字符輸入流 Reader
字符輸出流 Writer
註意:
A:四個頂層類都是抽象類。
B:一般每個體系的流都是以基類作為後綴名。
什麽時候使用誰?
如果文件能夠通過記事本打開並讀懂,就用字符流。
其他的全部使用字節流。
3:字節流(掌握)
InputStream
|--FileInputStream
|--BufferedInputStream
OutputStream
|--FileOutputStream
|--BufferedOutputSteam
掌握:(4種方式)
是否使用數組
是否使用高效
把c:\\a.jpg復制到d:\\b.jpg中。
---------------------------------------
4、例子
(1):使用普通字節流完成文件復制
一次一個字節 188毫秒
一次一個字節數組 0毫秒
package cn; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /** * 文件復制: * (1)使用普通字節流,一次一個字節的復制。 * (2)使用普通字節流,一次復制一個字節數組。 */ public class Demo4 { public static void main(String[] args) throws IOException { long currentTimeMillis = System.currentTimeMillis(); //method(); //188毫秒 method2(); //1毫秒 long currentTimeMillis2 = System.currentTimeMillis(); System.out.println(currentTimeMillis2 - currentTimeMillis); } //(1)一次一個字節的復制。 public static void method() throws IOException { //創建流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //讀 int c; while ((c = fis.read()) != -1) { //寫 fos.write(c); } //關閉流 fis.close(); fos.close(); } //(2)一次一個字節數組的復制。 public static void method2() throws IOException { //創建流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //讀 byte[] bytes = new byte[1024];//創建自己數組 int len;//保存每次讀取的字節的長度 while ((len = fis.read(bytes)) != -1) { /* String s= new String(bytes,0,len); //寫 fos.write(s.getBytes());*/ fos.write(bytes, 0, len); } //關閉流 fis.close(); fos.close(); } }View Code
(2):使用高效字節流完成文件復制
一次一個字節 6毫秒
一次一個字節數組 0毫秒
package cn; import java.io.*; /** * (1)使用高效字節流,一次復制一個字節 * (2)使用高效字節流,一次復制一個字節數組 */ public class Demo5 { public static void main(String[] args) throws IOException { long currentTimeMillis = System.currentTimeMillis(); // method(); //6毫秒 method2(); //0毫秒 long currentTimeMillis2 = System.currentTimeMillis(); System.out.println(currentTimeMillis2 - currentTimeMillis); } //(1)使用普通字節流,一次復制一個字節數組 public static void method() throws IOException { //創建輸入、輸出流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //創建高效輸入、輸出流對象 BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); //讀 int c; while ((c = bis.read()) != -1) { //寫 bos.write(c); } //關閉流 bos.close(); bis.close(); } //(2)使用高效字節流,一次復制一個字節數組 public static void method2() throws IOException { //創建輸入、輸出流對象 FileInputStream fis = new FileInputStream("b.txt"); FileOutputStream fos = new FileOutputStream("b2.txt"); //創建高效輸入、輸出流對象 BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); //讀 int len; byte[] bytes = new byte[1024]; while ((len = bis.read(bytes)) != -1) { //寫 bos.write(bytes, 0, len); bos.flush(); } //關閉流 bos.close(); bis.close(); } }View Code
(3):比較四種方式的運算時間,並總結規律。
遞歸、字節流、文件復制_DAY20