# 目标

  • 能够说出File对象的创建方式
  • 能够使用File类常用方法
  • 能够辨别相对路径和绝对路径
  • 能够遍历文件夹X
  • 能够解释递归的含义
  • 能够使用递归的方式计算5的阶乘
  • 能够说出使用递归会内存溢出隐患的原因
  • 能够说出IO流的分类和功能
  • 能够使用字节输出流写出数据到文件
  • 能够使用字节输入流读取数据到程序
  • 能够理解读取数据read(byte[])方法的原理
  • 能够使用字节流完成文件的复制
  • 能够使用FileWriter写数据的5个方法
  • 能够说出FileWriter中关闭和刷新方法的区别
  • 能够使用FileWriter写数据实现换行和追加写
  • 能够使用FileReader读数据一次一个字符
  • 能够使用FileReader读数据一次一个字符数组

# File类

# File类作用

File类作用:

  • java.io.File代表操作系统的文件/文件夹对象
  • 通过File对象操作文件和文件夹。

# File类构造器

File类是通过路径名定位文件和文件夹。

方法名 说明
File(String pathname) 通过路径名字符串创建File对象
File(String parent, String child) 从父路径名字符串和子路径名字符串创建File对象
File(File parent, String child) 从父抽象路径名和子路径名字符串创建File对象

斜杠问题:

  • \在字符串中要写2个 \
  • Windows系统中路径支持 \和/
  • Linux系统只支持/

File封装的对象仅仅是一个路径名。这个路径可以是存在的,也可以是不存在的。

import java.io.File;

/*
目标:File类构造方法(重点)

File类说明:
    File代表操作系统的文件/文件夹对象
    File类提供了诸如:获取文件的信息、删除文件、创建文件(文件夹)等功能。

File类构造器:
    1.File(String pathname) 通过字符串路径创建File对象(重要)
    2.File(String parent, String child) 通过父路径和子路径创建File对象
    3.File(File parent, String child) 通过父路径File对象和子路径创建File对象

注意:
    在windows中路径支持: \和/ 默认是\
    字符串中\要写两个: \\
*/

public class Demo1 {
    public static void main(String[] args) {
        // 1.File(String pathname) 通过字符串路径创建File对象(重要) 定位到一个文件或文件
        File file1 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc");
        System.out.println("file1 " + file1); // file1 D:\learn\java\code\javaUp\day10\src\doc

        // 2.File(String parent, String child) 通过父路径和子路径创建File对象
        File file2 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src", "doc");
        System.out.println("file2 " + file2); // file2 D:\learn\java\code\javaUp\day10\src\doc

        // 3.File(File parent, String child) 通过父路径File对象和子路径创建File对象
        File parent = new File("D:\\learn\\java\\code\\javaUp\\day10\\src");
        File file3 = new File(parent, "doc");
        System.out.println("file3 " + file3); // file3 D:\learn\java\code\javaUp\day10\src\doc
    }
}

# File类删除功能

方法名 说明
public boolean delete() 删除文件或文件夹

删除目录时的注意事项:

  • delete方法直接删除不走回收站。
  • 如果删除的是一个文件,直接删除。
  • 如果删除的是一个文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。
import java.io.File;

/*
目标:File类删除功能(重点)

File类删除功能:
    boolean delete() 可以删除文件和文件夹,删除成功返回true

删除目录时的注意事项:
    delete方法直接删除不走回收站。
    如果删除的是一个有内容文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。

*/
public class Demo {
    public static void main(String[] args) {
        // 1.boolean delete() 可以删除文件,删除成功返回true
        File file1 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\02");
        System.out.println(file1.delete()); // true

        // 2.boolean delete() 删除空文件夹
        System.out.println(file1.delete()); // false

        // 3.有内容的文件夹,需要先删除文件夹里面的内容,再删除空文件夹
        File file2 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\03");
        File file3 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\03\\1.txt");
        System.out.println(file3.delete()); // true
        System.out.println(file2.delete()); // true
    }
}

# File类创建功能

方法名 说明
public boolean createNewFile() 创建一个新的文件
public boolean mkdir() 创建一个单级文件夹
public boolean mkdirs() 创建一个多级文件夹
import java.io.File;
import java.io.IOException;

/*
目标:File类创建功能(重点)

File类创建功能:
    1.boolean createNewFile() 创建新文件, true表示创建成功
    2.boolean mkdir() make directory 创建单级文件夹, true表示创建成功
    3.boolean mkdirs() 创建多级文件夹, true表示创建成功
*/
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 1.boolean createNewFile() 创建新文件, true表示创建成功
        File file1 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\1.txt");
        System.out.println(file1.createNewFile()); // true

        // 2.boolean mkdir() make directory 创建单级文件夹, true表示创建成功
        File file2 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\1");
        System.out.println(file2.mkdir()); // true

        // 3.boolean mkdirs() 创建多级文件夹 (建议使用)
        File file3 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\1\\2\\3");
        System.out.println(file3.mkdirs()); // true
    }
}

# 绝对路径和相对路径

绝对路径:从盘符开始,如:File file1 = new File("D:\\MyFileTest\\aaa\\bbb.flv");
相对路径:不带盘符,默认从当前项目下的开始寻找,如:File file1 = new File("模块名\\xxx.png");

import java.io.File;
import java.io.IOException;

/*
目标:绝对路径和相对路径(了解)
绝对路径: 从盘符开始
    File file1 = new File("D:\\MyFileTest\\aaa\\bbb.flv");

相对路径: 不带盘符,默认从当前项目下的开始寻找
    File file1 = new File("模块名\\xxx.png");

注意:
    要使用相对路径.模块一定要放到项目里面
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 绝对路径
        File file1 = new File("D:\\learn\\java\\code\\javaUp\\day10\\src\\doc\\绝对路径.txt");
        System.out.println(file1.createNewFile()); // true

        // 相对路径
        File file2 = new File("day10\\src\\doc\\相对路径.txt");
        System.out.println(file2.createNewFile()); // true
    }
}

# File类判断和获取功能

方法名 说明
public boolean isDirectory() 判断是否是文件夹
public boolean isFile() 判断是否是文件
public boolean exists() 判断是否存在
public String getAbsolutePath() 返回File对象的绝对路径
public String getName() 获取名字
public String getParent() 获取父路径
public long length() 获取文件大小
import java.io.File;

/*
目标:File类获取功能(了解)

File类可以获取文件或文件夹相关信息
    String getAbsolutePath() 获取绝对路径
    String getName() 获取名字, 获取路径中最后一个\右边的
    String getParent() 获取父路径,最后一个\左边的
    long length() 获取"文件"大小, 文件夹不行
 */
public class Demo1 {
    public static void main(String[] args) {
        // 文件
        File file1 = new File("day10\\src\\doc\\1.txt");
        // 文件夹
        File file2 = new File("day10\\src\\doc");

        // String getAbsolutePath() 获取绝对路径
        System.out.println(file1.getAbsolutePath()); // D:\learn\java\code\javaUp\day10\src\doc\1.txt
        System.out.println(file2.getAbsolutePath()); // D:\learn\java\code\javaUp\day10\src\doc

        // String getName() 获取名字 路径中最后一个\\右边的就是名字
        System.out.println(file1.getName()); // 1.txt
        System.out.println(file2.getName()); // doc

        // String getParent() 获取父路径 路径中最后一个\\左边的就是父路径
        System.out.println(file1.getParent()); // day10\src\doc
        System.out.println(file2.getParent()); // day10\src

        // long length() 获取"文件"大小, 单位是字节, 文件夹无法获取准确大小
        System.out.println(file1.length()); // 5239
        System.out.println(file2.length()); // 0 肯定不对,不能用于判断文件夹大小

        File file = new File("day10\\src\\doc\\1.txt");
        File dir = new File("day10\\src\\doc");

        // 1.boolean isDirectory() 是否是文件夹, 如果是文件夹返回true
        System.out.println(file.isDirectory()); // false
        System.out.println(dir.isDirectory()); // true

        // 2.boolean isFile() 是否是文件, 如果是文件返回true
        System.out.println(file.isFile()); // true
        System.out.println(dir.isFile()); // false

        // 3.boolean exists() 判断是否存在, 只要存在就返回true
        System.out.println(file.exists()); // true
        System.out.println(dir.exists()); // true
    }
}

# File类遍历功能

File类的listFiles()可以显示文件夹中的所有内容(相当于双击文件夹)。

方法名 说明
String[] list() 获取文件夹里面的内容,以字符串的形式返回
public File[] listFiles() 获取文件夹里面的内容,以File对象的形式返回

注意:只有文件夹才能调用 listFiles()。

import java.io.File;

/*
目标:学习File遍历文件夹

以前我们学过数组或集合的遍历:遍历就是取出里面的所有数据

什么是遍历文件夹?
    获取文件夹中的所有内容(相当于双击文件夹)

File类的listFiles()可以显示文件夹中的所有内容。

注意:
    文件调用listFiles会返回null
    只能listFiles遍历文件夹中的内容
 */
public class Demo {
    public static void main(String[] args) {
        // 创建File对象
        File file = new File("day10\\src\\doc");

        // 获取文件夹所有内容,返回文件名字符串(了解)
        String[] fileNames = file.list();
        for (String name:fileNames) {
            System.out.println(name);
        }

        // public File[] listFiles() 获取文件夹中的所有内容
        File[] files = file.listFiles();
        for (File fileItem:files) {
            System.out.println(fileItem);
        }
    }
}

# 递归

# 递归概念

什么是递归?简单来说就是方法自己调用自己。
递归注意事项:

  • 递归要有出口 (递归要能够停下来)
  • 递归次数不能太多,要不容易爆栈
/*
目标:学习递归的概念

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

递归注意事项
    递归要有出口 (递归要能够停下来)
    递归次数不能太多
 */
public class Demo {
    private static int number;
    public static void main(String[] args) {
        diGui();
    }

    public static void diGui() {
        number++;
        System.out.println(number);

        if (number <= 500) {
            diGui();
        }
    }
}

# 递归求1 ~ n的和

递归思想:把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
递归解决问题要找到两个内容:

  • 递归出口:否则会出现内存溢出
  • 递归规则:与原问题相似的规模较小的问题
/*
目标:使用递归求1-5的和

递归思想
    把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
    递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算

    1-5的和:1+2+3+4+5以前使用for循环
    使用递归求1-5的和

递归解决问题要找到两个内容
    递归规则:与原问题相似的规模较小的问题
    递归出口:否则会出现内存溢出

经验:
    在以后工作中能使用循环的不要使用递归
    只有遇到文件夹中还要处理文件夹,使用递归

递归内存溢出的原因:
    递归是方法不断调用自己,方法不断进入栈中,栈的空间不够了,就溢出了
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(sum(5));
    }
    static int sum(int n) {
        if (n <= 1) return 1;

        return n + sum(n - 1);
    }
}

# 递归案例-文件搜索

列出指定文件夹中的所有 Java 文件,如果文件夹中有文件夹也要找出来

import java.io.File;

/*
目标:列出文件夹中的所有java文件,如果文件夹中有文件夹也要找出来
    // 1.创建一个File对象定位aaa文件夹
    // 2.定义一个方法listJava(File dir), 列出某个文件夹中的所有java文件
    // 2.1.调用listFiles()显示文件夹中的所有内容
    // 2.2.遍历获取每个内容
    // 2.3.判断如果是文件,并且是.java文件,打印这个文件
    // 2.4.如果是文件夹,再次调用listJava
 */
public class Demo {
    public static void main(String[] args) {
        File file = new File("day10\\src\\doc");
        searchFile(file, ".java");
    }
    public static void searchFile(File file, String type) {
        File[] files = file.listFiles();

        for (File fileItem : files) {
            if (fileItem.isDirectory()) {
                searchFile(fileItem, type);
            } else if (fileItem.isFile() && fileItem.getName().endsWith(type)) {
                System.out.println(fileItem);
            }
        }
    }
}

# IO流的概述和分类

# IO流作用和分类

数据存在的内存中的问题不能永久化存储,只要代码运行结束,所有数据都会丢失。
想永久存储数据怎么办呢?将数据存储在文件中。

IO流的概念:

  • I表示intput,输入。
  • O表示output,输出。

IO流的作用:

  • 将数据写到文件中,实现数据永久化存储
  • 读取文件中的数据到程序

按流向分 (站在程序的角度):

  • 输入流
  • 输出流

按操作数据类型分:

  • 字节流
  • 字符流

image.png
image.png

# 字节流

image.png

# 字节流写一个字节数据

字节输出流的顶级父类OutputStream是抽象的, 我们可以使用它的子类FileOutputStream操作文件。FileOutputSteam文件字节输出流,把程序中的字节数据写到文件。

方法名 说明
void write(int b) 一次写一个字节数据
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据

字节流写数据的步骤:

  • 创建字节输出流对象
  • 写数据
  • 关闭流

# 字节流写多个字节数据

方法名 说明
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据

# 字节流读一个字节数据

字节输入流的顶级父类InputStream是抽象的, 我们可以使用它的子类FileInputStream操作文件。FileInputSteam文件字节输入流,读文件中的字节数据到程序。

方法名 说明
int read() 从流中读取一个字节
int read(byte[] b) 从流中读取多个字节保存参数的数组中

字节流读数据的步骤:

  • 创建字节输入流对象
  • 读取数据
  • 释放资源

一次读取一个字节存在的问题:效率低
一次读取一个字节循环读取所有数据:????

int b; // 定义一个变量保存每次读取到的数据
while ((b = fis.read()) != -1) {
    // 读取到内容
    System.out.println((char) b);
}

# String和byte数组转换API

String转成byte[]:

方法名 说明
byte[] getBytes() 将String的内容转成byte[]

byte[]转成String:

方法名 说明
String(byte bytes[]) 将byte[]的内容转成String
String(byte bytes[], int offset, int length) 将byte[]的部分内容转成String

# 字节流读多个字节数据

方法名 说明
int read(byte[] b) 从流中读取多个字节保存参数的数组中

字节流读数据的步骤:

  • 创建字节输如流对象
  • 读取数据
  • 释放资源

一次读取多个字节好处:效率高
一次读取多个字节循环读取所有数据:????

// 定义一个数组保存读取到的数据
byte[] buf = new byte[4];
int len; // 定义一个变量保存读取的数量
while ((len = fis.read(buf)) != -1) {
    // 读取到内容
    System.out.println(new String(buf, 0, len));
}

# 字节流案例-文件复制

需求:使用字节流将 "study_day10/abc/xyz.png" 复制到 "D:/MyFileTest/xyz.png"
复制文件的本质是什么:两个文件的字节数据一样
复制文件的步骤:

  • 创建输入流
  • 创建输出流
  • 循环读写数据
  • 关闭流

# 字符流

# 字符流读一个字符

# 字符流读多个字符

# 字符流写数据

# 数据追加续写和换行