递归、字节流、文件复制_DAY20

1:递归(理解)

    (1)方法定义中调用方法本身的现象。

    (2)递归注意事项:

       A:要有出口,否则就是死递归。

       B:次数不能太多,否则内存溢出。

       特殊事项:构造方法不能递归定义。

    例子:cn.itcast.demo

package cn.itcast;
/*
 * 递归算法:
 *         自己调用自己。
 *         方法内定义:调用到什么程度,就不调用自己了。即递归出口。
 */
public class Demo {

    public static void main(String[] args) {

        method(5);
    }
    
    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;
        }
    }

}
View Code

    (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
 */
public class 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);
        }
    }
}
View Code

       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)