人生苦短我学Java-15-递归、文件IO/字节/字符/转换/打印流

一、递归

什么是递归?方法内调用自己

注意事项:

  • 递归方法内需要有个return 出口,非继续递归
  • 递归次数不宜过多,否则堆栈溢出程序报错

 1.递归:5的阶乘

// 递归:5的阶乘
public static int factorial(int n) {
    if (n == 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

2.递归:斐波那契数列:1 1 2 3 5 8

// 斐波那契数列:1 1 2 3 5 8
public static int fibonacci(int n) {
    if (n == 1 || n == 2) {
        return 1;
    }
    return fibonacci(n - 2) + fibonacci(n - 1);
}

3.递归删除文件夹与文件

// 递归删除文件夹与文件
public static boolean del(File file) {
    if (!file.isDirectory() || !file.exists()) {
        return false;
    }
    File[] files = file.listFiles();
    for (File f : files) {
        if (f.isDirectory()) {
            del(f);
        } else f.delete();
    }
    return file.delete();
}

 递归深度过大报错如下:

package com.ppl.other;

/*
com.ppl.other:学习项目
@user:广深-小龙
@date:2022/3/19 10:00
--递归
*/

import java.io.File;

public class Factorial {
    public static void main(String[] args) {
        // 注意递归次数不可以过多,否则递归深度太深导致堆栈溢出报错:StackOverflowError
        System.out.println("阶乘:" + factorial(5));
        System.out.println("斐波那契:" + fibonacci(10));
        File file = new File("aaa");
        System.out.println(del(file));
        Java(new File("src"));

    }

    // 递归:5的阶乘
    public static int factorial(int n) {
        if (n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }

    // 斐波那契数列:1 1 2 3 5 8
    public static int fibonacci(int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fibonacci(n - 2) + fibonacci(n - 1);
    }

    // 递归删除文件夹与文件
    public static boolean del(File file) {
        if (!file.isDirectory() || !file.exists()) {
            return false;
        }
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                del(f);
            } else f.delete();
        }
        return file.delete();
    }

    // 递归查询.java文件
    public static void Java(File file) {
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                Java(f);
            } else {
                if (f.getName().endsWith("java")) {
                    System.out.println(f.getAbsolutePath());
                }
            }
        }
    }
}
View Code

 二、file文件流

JAVA操作文件对象,使用File类主要用于文件和文件夹的创建、查询、删除等

样例:

package com.ppl.other;
/*
com.ppl.other:学习项目
@user:广深-小龙
@date:2022/3/19 10:22
--文件对象
*/

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class MyFile {
    String path = "C:\\Users\\PPL\\Desktop";
    String fileName = "api.txt";

    public static void main(String[] args) throws IOException {
        new MyFile().structure();
        new MyFile().member();

    }

    // 常用成员方法
    public void member() throws IOException {
        File file = new File(fileName);
        File file1 = new File("test");
        // 创建单个文件夹
        boolean isMkdir = file1.mkdir();
        // 创建多级文件夹
        boolean isMkdirs = new File("tests/ppl").mkdirs();
        // 创建文件 createNewFile()
        boolean isCreate = file.createNewFile();
        // 判断文件是否存在 exists()
        boolean exists = file.exists();
        // 删除文件或文件夹
        // 注意:如果要删除的文件夹里还有子文件或者子文件夹的话,是没法删除成功,必须先把子文件和文件夹都删除掉,才能删除自身
        boolean isDel = file.delete();
        boolean isDel1 = file1.delete();
        boolean isDel2 = new File("tests/ppl").delete();
        boolean isDel3 = new File("tests").delete();
        // 判断是不是 文件对象 isFile()
        boolean isFile = new File("src").isFile();
        // 判断是不是 文件夹对象 isDirectory()
        boolean isDirectory = new File("src").isDirectory();
        // 获取字节长度
        File file2 = new File("README.md");
        System.out.println(file2.length());
        // 获取文件或文件夹的名字
        String fileName = file.getName();
        // 获取文件或文件夹的相对路径
        String filePath = file.getPath();
        // 获取文件或文件夹的绝对路径
        String absFilePath = file.getAbsolutePath();
        System.out.println(absFilePath);
        // 获取文件夹下的所有文件或文件夹
        File file3 = new File("project");
        File[] files = file3.listFiles();
        System.out.println(Arrays.toString(files));
    }

    // 常见构造方法
    public void structure() {
        // 常见构造方法1 public File(String pathname)
        File file1 = new File(fileName);// 相对路径
        System.out.println(file1 + " " + file1.exists());

        // 常见构造方法2 public File(String parent, String child)
        // 父+子path拼接
        File file2 = new File(path, fileName);// 绝对路径
        System.out.println(file2 + " " + file2.exists());

        // 常见构造方法3 public File(File parent, String child)
        // 父file+子path拼接
        File file3 = new File(path);// 绝对路径
        File file4 = new File(file3, fileName);// 绝对路径
        System.out.println(file4 + " " + file4.exists());
    }
}
View Code

什么是IO流?

  • I:input,是指输入,读取文件。
  • O:output,是指输出,写入文件。
  • 流:数据传输传递过程。

 1、FileInputStream

class MyOutput {
    // 创建字节输入或输出流对象,如果文件不存在会创建;注意:需要文件路径,不能是文件夹
    public void member() throws IOException {
        // 1.FileOutputStream(String name) name:文件名
        FileOutputStream fos = new FileOutputStream("README.md");

        // 2.FileOutputStream(File file) 文件输出流对象
        File file = new File("README.md");
        FileOutputStream fos1 = new FileOutputStream(file);

        // 3.write(int b) 向文件输出一个字节数据 (单字节字符)
        FileOutputStream fos2 = new FileOutputStream("test.txt");
        fos2.write(97);
        // ---换行符: \r\n
        fos2.write("\r\n".getBytes());
        // 4.write(byte[] b) 向文件输出一个字节数组数据
        byte[] bytes = {97, 98, 99};
        fos2.write(bytes);
        // 5.write(byte b[], int off, int len) 向文件输出自定义字节数组范围数据,如0-2个
        fos2.write(bytes, 0, 2);
    }

    public void structure() throws IOException {
        // 追加输出到文件:FileOutputStream(String name, boolean append)
        FileOutputStream fos = new FileOutputStream("test.txt", true);
        fos.write("\n这是一个换行的追加开始呀".getBytes());
        fos.write("\nend".getBytes());
    }
}

2、FileOutputStream

class MyOutput {
    // 创建字节输入或输出流对象,如果文件不存在会创建;注意:需要文件路径,不能是文件夹
    public void member() throws IOException {
        // 1.FileOutputStream(String name) name:文件名
        FileOutputStream fos = new FileOutputStream("README.md");

        // 2.FileOutputStream(File file) 文件输出流对象
        File file = new File("README.md");
        FileOutputStream fos1 = new FileOutputStream(file);

        // 3.write(int b) 向文件输出一个字节数据 (单字节字符)
        FileOutputStream fos2 = new FileOutputStream("test.txt");
        fos2.write(97);
        // ---换行符: \r\n
        fos2.write("\r\n".getBytes());
        // 4.write(byte[] b) 向文件输出一个字节数组数据
        byte[] bytes = {97, 98, 99};
        fos2.write(bytes);
        // 5.write(byte b[], int off, int len) 向文件输出自定义字节数组范围数据,如0-2个
        fos2.write(bytes, 0, 2);
    }

    public void structure() throws IOException {
        // 追加输出到文件:FileOutputStream(String name, boolean append)
        FileOutputStream fos = new FileOutputStream("test.txt", true);
        fos.write("\n这是一个换行的追加开始呀".getBytes());
        fos.write("\nend".getBytes());
    }
}

复制文件例子:

class CopyDemo {
    public static void main(String[] args) throws IOException {
        demo1();
        demo2();

    }

    public static void demo1() throws IOException {
        // 第一种
        // 输入流:读取文件
        FileInputStream fii = new FileInputStream("README.md");
        // 输出流:写文件
        FileOutputStream fio = new FileOutputStream("test.txt");
        // 读取文件内容重写如另一个文件:一次读一个字节
        int by = 0;
        while ((by = fii.read()) != -1) {
            fio.write(by);
        }
        // 关闭流
        fii.close();
        fio.close();
    }

    public static void demo2() {
        // 第二种 + 自定义抛异常
        FileInputStream fis1 = null;
        FileOutputStream fio1 = null;
        try {
            // 输入流:读取文件
            fis1 = new FileInputStream("README.md");
            // 输出流:写文件
            fio1 = new FileOutputStream("test.txt");
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = fis1.read(bytes)) != -1) {
                fio1.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {                 // finally 是否抛异常都会执行的代码块
            if (fis1 != null) {
                try {
                    fis1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fio1 != null) {
                try {
                    // 关闭流
                    fio1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
BufferedInputStream、BufferedOutputStream
高效缓冲流:
package com.ppl.other;
/*
com.ppl.other:学习项目
@user:广深-小龙
@date:2022/4/4 10:55
*/

import java.io.*;

public class MyBufferStream {
    public static void main(String[] args) throws IOException {
        // 缓冲字节输入流:传入new对象为装饰设计模式
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("README.md"));
        byte[] bytes = new byte[5];
        int len = bis.read(bytes);
        while ((len = bis.read(bytes)) != -1) {
            String str = new String(bytes, 0, len);
            System.out.println(len + ":" + str);
        }
        // 缓冲字节输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
        bos.write(97);
        bos.write(98);
        // 写完后需要刷新缓冲区
        bos.flush();

        // copy
        copy();
    }

    public static void copy() throws IOException {
        // 复制文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }
        bis.close();
        bos.close();
    }
}

三、字符流

为什么有字符流:中文一个文字占3个字节,所以我们使用字节流读取文件可能会出现中文乱码。因为字符流一个中文或者一个符合就是一个字符。

推荐我们使用高效流

  1. FileReader:普通输入流
  2. FileWriter:普通输出流
  3. BufferedReader:高效输入流,读取推荐使用 readLine 方法 或数组字节读取。
  4. BufferedWriter:高效输出流,换行推荐使用 newLine 方法。
package com.ppl.other;
/*
com.ppl.other:学习项目
@user:广深-小龙
@date:2022/4/17 23:14
*/

import java.io.*;

public class MyStrFlow {
    public static void main(String[] args) throws IOException {
        myRead();
        myWrit();
        myBuffRead();
        myBuffWrit();

        // BufferedReader一行一行读,特有方法:readLine()
        BufferedReader fr = new BufferedReader(new FileReader("README.md"));
        String str = null;
        while ((str = fr.readLine()) != null) {
            System.out.println(str);
        }

        // BufferedWriter换行写入数据,特有方法:newLine()
        BufferedWriter bfw = new BufferedWriter(new FileWriter("a.txt", true));
        bfw.newLine();
    }

    public static void myBuffRead() throws IOException {
        // 输入流
        BufferedReader fr = new BufferedReader(new FileReader("README.md"));
        long start = System.currentTimeMillis();

        // 单个读
        int ch = 0;
        while ((ch = fr.read()) != -1) {
            System.out.print((char) ch);
        }
        // 多个读
        char[] chs = new char[1024];
        int len = 0;
        while ((len = fr.read(chs)) != -1) {
            System.out.print(new String(chs));
        }
        long end = System.currentTimeMillis() - start;
        System.out.println("耗时:" + end);
    }

    public static void myBuffWrit() throws IOException {
        BufferedWriter bfw = new BufferedWriter(new FileWriter("a.txt", true));
        bfw.write("高效:测试写入字符串\n");
        bfw.write("高效:123456asdasd\n");
        bfw.write("高效:@%#$$%#$%\n");
        bfw.close();
    }

    public static void myRead() throws IOException {
        // 输入流
        FileReader fr = new FileReader("README.md");

        // 单个读
        int ch = 0;
        while ((ch = fr.read()) != -1) {
            System.out.print((char) ch);
        }
        // 多个读
        long start = System.currentTimeMillis();
        char[] chs = new char[1024];
        int len = 0;
        while ((len = fr.read(chs)) != -1) {
            System.out.print(new String(chs));
        }
        long end = System.currentTimeMillis() - start;
        System.out.println("耗时:" + end);
    }

    public static void myWrit() throws IOException {
        FileWriter fw = new FileWriter("a.txt", true);
        fw.write("测试写入字符串\n");
        fw.write("123456asdasd\n");
        fw.write("@%#$$%#$%\n");
        fw.close();
    }
}

四、转换流

package com.ppl.other;
/*
com.ppl.other:学习项目
@user:广深-小龙
@date:2022/4/20 20:32
*/

import java.io.*;

public class MyOtherFlow {
    /* 其它流,方法和前面的是一样的。
    什么是转换率?
    可以将字节流转换成字符流
    */
    public static void main(String[] args) throws IOException {
        myFlowReader();
        myFlowWriter();
        buffFlowReader();
        buffFlowWriter();
    }

    // 普通转换输入流
    public static void myFlowReader() throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("README.md"));
        char[] chs = new char[1024];
        int len = 0;
        while ((len = isr.read(chs)) != -1) {
            System.out.print(new String(chs));
        }
    }

    // 普通转换输出流
    public static void myFlowWriter() throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("README.md", true));
        osw.write("高效:测试写入字符串\n");
    }

    // 高效转换输入流
    public static void buffFlowReader() throws IOException {
        BufferedReader isr = new BufferedReader(new InputStreamReader(new FileInputStream("README.md")));
        char[] chs = new char[1024];
        int len = 0;
        while ((len = isr.read(chs)) != -1) {
            System.out.print(new String(chs));
        }
    }

    // 高效转换输出流
    public static void buffFlowWriter() throws IOException {
        BufferedWriter osw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("README.md")));
        osw.write("高效:测试写入字符串\n");
    }
}

五、打印流

只有输出流

package com.ppl.other.Flow;
/*
com.ppl.other.Flow:学习项目
@user:广深-小龙
@date:2022/4/20 21:14
*/

import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class MyPrint {
    // 打印流
    public static void main(String[] args) throws FileNotFoundException {
        PrintWriter pw = new PrintWriter("t.md");
        pw.write("不不不哈哈");
        pw.println("123213131");
        pw.flush();
    }
}

总结:

IO流的选择 在以后对文件进行复制的时候,到底该选择哪个流进行复制?

  • 1.如果文件打开之后,你看不懂,就使用高效字节流
  • 2.如果文件打开之后,你看得懂,就使用高效字符流,也可以使用高效字节流
  • 3.如果有需求需要将字节流转换成字符流,那就使用高效转换流,也还可以指定编码

一般mp4,mp3,jpg,png...这些文件我们是看不懂的 一般.txt,.java这些文件我们是看得懂的

posted @ 2022-04-20 21:39  广深-小龙  阅读(40)  评论(0编辑  收藏  举报