day08 File类 递归笔记 今日内容java
File类:
IO流, 操作磁盘上的文件(文件夹/目录)
递归:
方法自己调用自己
思想: 大问题解决不了 = 可以解决的一个小问题 + 无法解决的另一个小问题
无法解决的另一个小问题 = 可以解决的一个小问题 + 无法解决的另一个小问题
...
无法解决的另一个小问题 -> 可以解决的小问题
综合案例
File和递归结合
File类
File类概述知识点:
File类用于描述什么事物
我们可以对File进行哪些操作
总结:java
java.io.File类: "文件"和"目录"的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
private String path;
"D:\itheima-teach\sjz-javaee-10\s2-进阶\08\avi\02_File类的概述.avi"
"D:\itheima-teach\sjz-javaee-10\s2-进阶\"
String -> File
Input输入 Output输出我们可以对File进行的操作:
创建文件/目录
删除文件/目录
获取文件/目录
判断文件/目录是否存在
对目录进行遍历
获取文件的大小
重要英文单词的含义: (起变量名时会用到)
file: 文件
directory: 目录
path: 路径
补充:java File类的静态成员变量知识点:
File类中的静态成员变量, 分别表示什么
总结:java
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 静态成员变量
static String pathSeparator: 路径分隔符的字符串形式
static char pathSeparatorChar: 路径分隔符的char形式
Windows系统是 分号;
Linux系统是 冒号:
static String separator: 文件名称分隔符的字符串形式
static char separatorChar: 文件名称分隔符的char形式
Window系统是 反斜杠\
Linux系统是 正斜杠/
补充:java 绝对路径和相对路径知识点:
什么是绝对路径
什么是相对路径, 相对于哪里
总结:java
绝对路径:
以盘符开始的路径
如: "D:\\a\\hi.txt"
相对路径:
不以盘符开始的简化路径. IDEA项目, 相对于项目的根目录
如: "a\\1.mp3", "123.txt"
"d:\\t"
注意事项:
1. 路径不区分大小写 (在Windows系统中不区分大小写, Linux, Mac区分)
2. 路径一般写成字符串, 而字符串中一个\是转义, 所以要写两个\\
补充:java File类: 构造方法知识点:
如何通过File类的构造方法, 将文件路径封装为File对象
总结:java
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
new File("D:\\a\\hi.txt")
"D:\\a\\b\\c\\hi.txt"
"D:\\a\\" "b\\c\\hi.txt"
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
补充:java
public class Test {
public static void main(String[] args) {
File f1 = new File("z:\\z.txt"); // 不存在的路径也可以创建File对象
System.out.println(f1); File f2 = new File("目录\\", "a.txt"); // 相对路径也可以
System.out.println(f2); File f3 = new File(new File("d:\\"), "c.txt");
System.out.println(f3); // 创建File对象后, 并不会在磁盘上创建文件或目录!
}
}
long -> Date/Calendar 方法
String -> File 方法
File类: 获取方法知识点:
哪个方法可以获取File对象的路径
哪个方法可以获取File对象所表示的文件名或目录名
哪个方法可以获取File对象所表示的文件的大小
总结:java
java.io.File类
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名 d:\a\b\c\aaa.txt
long length(): 获取File表示的"文件"大小的字节byte数 (不能获取目录的大小)
补充:java 5分钟练习: 测试获取方法java
需求:
测试File类的获取方法:
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
代码:java
public class Test {
public static void main(String[] args) {
// String getAbsolutePath(): 返回此File的绝对路径名字符串
File f1 = new File("d:\\a.txt"); // 测试使用绝对路径
String f1AbsolutePath = f1.getAbsolutePath();
System.out.println(f1AbsolutePath); // d:\a.txt File f2 = new File("a.txt"); // 测试使用相对路径, 只是将项目的路径拼接到当前相对路径之前, 并不检测路径是否真实
String f2AbsolutePath = f2.getAbsolutePath();
System.out.println(f2AbsolutePath); // D:\itheima-teach\sjz-javaee-11\s2-进阶\advance-code\a.txt // String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
File f3 = new File("d:\\a.txt"); // 测试使用绝对路径
String f3Path = f3.getPath();
System.out.println(f3Path); // d:\a.txt File f4 = new File("a.txt"); // 测试使用相对路径
String f4Path = f4.getPath();
System.out.println(f4Path); // a.txt // String getName(): 获取File对象的文件名或目录名
File f5 = new File("d:\\a\\b\\c\\a.txt");
String f5Name = f5.getName();
System.out.println(f5Name); // a.txt File f6 = new File("d:\\a\\b\\c");
String f6Name = f6.getName();
System.out.println(f6Name); // c // long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
File f7 = new File("day08\\src\\com\\itheima\\test01\\Test.java"); // 存在的文件
System.out.println(f7.length()); // 2407
File f8 = new File("z:\\a.txt"); // 不存在的文件
System.out.println(f8.length()); // 0
File f9 = new File("day08"); // 存在的目录
System.out.println(f9.length()); // 0
File f10 = new File("z:\\aaa"); // 不存在的目录
System.out.println(f10.length()); // 0 }
}
File类: 判断方法知识点:
哪个方法判断文件或目录存在
哪个方法判断File对象是目录
哪个方法判断File对象是文件
总结:java
java.io.File类
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
补充:java 5分钟练习: 测试判断方法java
需求:
测试File类的判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
代码:java
public class Test {
public static void main(String[] args) {
// boolean exists(): 判断File对象代表的文件或目录是否实际存在
File f1 = new File("day08"); // 传入存在的路径
System.out.println(f1.exists()); // true File f2 = new File("d:\\a.txt"); // 传入不存在的路径
System.out.println(f2.exists()); // false // boolean isDirectory(): 判断File表示的是否为目录
File f3 = new File("day08"); // 存在的目录
System.out.println(f3.isDirectory()); // true File f4 = new File("day08\\src\\com\\itheima\\test01\\Test.java"); // 存在的文件
System.out.println(f4.isDirectory()); // false File f5 = new File("sdfdfdsaf"); // 不存在的目录
System.out.println(f5.isDirectory()); // false // boolean isFile(): 判断File表示的是否为文件
File f6 = new File("day08\\src\\com\\itheima\\test01\\Test.java"); // 存在的文件
System.out.println(f6.isFile()); // true File f7 = new File("day08"); // 存在的目录
System.out.println(f7.isFile()); // false File f8 = new File("sdfdfdsaf.txt"); // 不存在的文件
System.out.println(f8.isFile()); // false
}
}
File类: 创建删除方法知识点:
哪个方法可以创建文件
哪个方法可以创建目录
哪个方法可以删除文件或目录
总结:java
java.io.File类
// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
false: 路径已经存在(无论文件还是目录)
抛IO异常: 写的路径不符合逻辑 (Y:\\a.txt\dsfsd)
boolean delete(): 删除由此File表示的文件或目录.
删除目录时: 必须是空目录
boolean mkdir(): 创建File表示的目录 "d:\\a\\b\\c\\我的目录"
false: 1. 路径已经存在(无论文件还是目录) 2. 写的路径不符合逻辑 (Y:\\a.txt\dsfsd)
boolean mkdirs(): 创建File表示的多级目录 "d:\\a\\b\\c\\我的目录"
false: 1. 路径已经存在(无论文件还是目录) 2. 写的路径不符合逻辑 (Y:\\a.txt\ds)
补充:java 5分钟练习: 测试创建删除方法java
需求:
在当前的模块中, 创建a目录(注意用相对路径时加上模块名) "day08\\a"
在a目录中创建b目录 "day08\\a\\b"
在b目录中创建b.txt文件和c.txt文件
删除c.txt文件
代码:java
public class Test {
public static void main(String[] args) throws IOException {
// 在当前的模块中, 创建a目录(注意用相对路径时加上模块名)
File aDir = new File("day08\\a");
boolean b1 = aDir.mkdir();
System.out.println("在当前的模块中, 创建a目录:" + b1); // 在a目录中创建b目录
File bDir = new File("day08\\a\\b");
boolean b2 = bDir.mkdirs();
System.out.println("在a目录中创建b目录:" + b2); // 在b目录中创建b.txt文件和c.txt文件
File bFile = new File("day08\\a\\b\\b.txt");
boolean b3 = bFile.createNewFile();
System.out.println("在b目录中创建b.txt文件:" + b3); File cFile = new File("day08\\a\\b\\c.txt");
boolean b4 = cFile.createNewFile();
System.out.println("在b目录中创建c.txt文件:" + b4); // 删除c.txt文件
boolean b5 = cFile.delete();
System.out.println("删除c.txt文件:" + b5);
}
}
File类: 遍历目录方法知识点:
哪个方法可以获取目录中的所有子文件和子目录的名称
哪个方法可以获取目录中的所有子文件和子目录的File对象
总结:java
java.io.File类
// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
注意:
只能用表示目录的File对象调用
用文件的File对象, 或者路径不存在, 调用会报错
补充:java 5分钟练习: 测试遍历目录方法java
需求:
利用 File[] listFiles() 遍历目录方法, 将当前模块目录下的文件或目录打印出来
代码:java
public class Test {
public static void main(String[] args) {
// 创建File对象, 指向当前模块
File dir = new File("day08"); File[] files = dir.listFiles();
for (File file : files) {
System.out.println(file);
}
/*
day08\a
day08\day08.iml
day08\src
*/
}
}
递归
递归的概念, 分类, 注意事项知识点:
代码中如何实现递归递归
什么是直接递归
什么是间接递归
使用递归要注意哪些问题, 有什么前提
总结:java
递归思想:
遇到一个问题时, 将该问题拆解成可以解决的小问题, 如果解决不了, 继续拆解为更小的问题. 如果小问题解决了, 大问题也就能够解决Java中实现递归的方式:
方法内部调用方法自己 (所以必须定义方法)递归的分类:
直接递归: 方法自己调用方法
间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法
递归时的注意事项:
1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出
2. 递归次数不能太多, 否则会栈内存溢出
3. 构造方法不能递归递归的使用前提:
调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归
补充:java 练习: 递归计算1~n的和
5分钟练习: 递归求和
需求: 求1~n的和 1~5 1+2+3+4+5
分析:
求1~5的和: 5+ 4+3+2+1
5~1的和 = 5 + ((5-1)~1的和)
4~1的和 = 4 + ((4-1)~1的和)
3~1的和 = 3 + (2~1的和)
2~1的和 = 2 + (1~1的和)
1~1的和 = 1;
求1~n的和: n+(n-1)+...+2+1
n~1的和 = n + ((n-1)~1的和)
...
1~1的和 = 1;
把解决不了的问题, 定义成方法 (定义方法求n~1的和)
如果小问题能解决: 直接写代码实现
如果小问题不能解决: 就递归调用方法实现
递归实现思路
将要解决的问题, 封装为方法
求1~n的和: 定义方法
private static int getSum(int n) { // 解决问题: 求n~1的和
// 出口(方法自己不再调用自己)
if (n == 1) {
return 1;
}
// n~1的和 = n + ((n-1)~1的和)
return n + getSum(n-1);
}
在方法内部, 拆解问题, 不能解决的小问题, 继续递归调用方法![](./img/02_递归求和的原理.bmp)代码:java
public class Test {
public static void main(String[] args) {
int sum = sum(5);
System.out.println(sum); // 15
} // 定义方法: 求1~n的和
public static int sum(int n) {
// 递归的结束出口
if (n == 1) { // 如果问题能解决, 直接返回结果
return 1;
}
// 如果能执行到这里, 说明问题没有解决, 要递归解决
return n + sum(n-1);
}
}
练习: 递归求n的阶乘
5分钟练习: 递归求阶乘`阶乘`: 一个数一直乘到1的积
5的阶乘: 5 * 4 * 3 * 2 * 1 乘积
15!需求: 使用递归计算5的阶乘
分析:
5! = 5* 4*3*2*1
5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 问题全都解决
n! = n * (n-1)!
...
1! = 1 问题全都解决
if (n == 1) {
return 1;
}
return n * (n-1)!递归实现思路
将要解决的问题, 封装为方法
求n的阶乘
private static int jc(int n) {
//出口
if (n == 1) {
return 1;
}
return n * jc(n-1);
}
代码:java
public class Test {
public static void main(String[] args) {
int jc = jc(5);
System.out.println(jc); // 120
} public static int jc(int n) {
// 结束条件
if (n == 1) {
return 1;
}
// 不能解决时, 递归调用方法
return n * jc(n - 1);
}
}
File[] listFiles()
for(File file : arr) {
if (是文件) {
直接操作
} else {
是目录, 就递归调用方法
}
}
代码:java
public class Test { public static void main(String[] args) {
File dir = new File("day08");
printAllFile(dir);
} // 将每次不能解决的问题, 定义成方法: 打印某个目录中的所有文件和目录路径
public static void printAllFile(File dir) { // 参数是目录的File对象
// 为了打印所有目录的路径, 在这里统一打印目录
System.out.println(dir); // 先获取传入的目录中的所有子文件和子目录
File[] childFiles = dir.listFiles(); // childFiles是一个变量名, 表示所有 子File对象
for (File childFile : childFiles) {
// 判断每个 子File对象 是文件还是目录
if (childFile.isFile()) {
// 是文件, 则打印路径
System.out.println(childFile);
} else if (childFile.isDirectory()) {
// 是目录, 则递归调用方法
printAllFile(childFile); // 注意!! 参数要传递 子目录对象!!!
}
}
}
} 综合案例
综合案例之多级目录搜索
5分钟练习: 递归遍历多级目录java
补充String类中的方法:
boolean endsWith(String suffix): 判断字符串是否以指定的字符串结尾
判断文件后缀: boolean b = "aaa.JAVA".endsWith(".java");
String toLowerCase(): 将字符串转为小写字母
String s = "aaa.JAVA".toLowerCase();
s: "aaa.java"需求: 打印当前模块中的.java文件 (包含子目录)aaa/
|_ bbb/
| | ccc/
| | |_ c1.java
| |
| |_ b1.java
| |_ b2.txt
|
|_ a1.java
|_ a2.txt递归思想分析:
大问题:
打印aaa目录下的"所有"java文件路径 = 判断java文件打印 + (打印bbb目录下的"所有"java文件路径)?
打印bbb目录下的"所有"java文件路径 = 判断java文件打印 + (打印ccc目录下的"所有"java文件路径)?
打印ccc目录下的"所有"java文件路径 = 判断java文件打印
要解决的问题(定义的方法): 打印 参数 目录下的"所有"java文件路径
代码实现:
出口: 没有子目录
共性的公式: 判断java文件打印 + 递归调用方法(打印ccc目录下的"所有"java文件路径)?
代码:java
public class Test {
public static void main(String[] args) {
File dir = new File("day08");
printJavaFile(dir);
} // 定义方法打印某个目录中的java文件
public static void printJavaFile(File dir) {
// 先获取当前目录中的所有子文件和子目录
File[] childFiles = dir.listFiles();
for (File childFile : childFiles) {
if(childFile.isFile()) {
// 是子文件, 则判断文件名是否是.java结尾
if (childFile.getName().toLowerCase().endsWith(".java")) {
System.out.println(childFile);
}
} else {
// 是子目录, 则递归调用, 查看子目录中的java文件
printJavaFile(childFile);
}
}
}
}
FileFilter文件过滤器的原理和使用知识点:java
如何使用 listFiles(FileFilter filter) 方法优化文件过滤的步骤
总结:java
java.io.File类: Filter过滤器
File[] listFiles(FileFilter filter): 返回文件过滤器过滤后的File对象数组
File[] listFiles(FilenameFilter filter): 返回文件过滤器过滤后的File对象数组java.io.FileFilter接口: 用于File对象的过滤器
boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入java.io.FilenameFilter接口: 将File对象拆分为父路径和子路径来判断的过滤器
boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入
dir: 被找到的文件所在的目录 (父路径)
name: 文件的名称 (子路径)
5分钟练习: 使用FileFilterjava
需求:
使用File[] listFiles(FileFilter filter)方法, 将当前模块中的.java文件过滤出来, 打印到控制台
代码:java
// 自定义 java文件过滤器
public class FileFilterImpl implements FileFilter {
@Override
public boolean accept(File pathname) {
// 规则:
// 如果是目录, 允许添加到数组, 因为我们需要目录来递归调用
// 如果是文件, 则判断是否为java文件, 是则允许添加到数组中 // 判断是不是目录
if (pathname.isDirectory()) {
// 允许添加到数组中
return true;
} // 如果能执行到这里, 说明不是目录, 那肯定是文件, 则判断文件名后缀
boolean isJavaFile = pathname.getName().toLowerCase().endsWith(".java");
return isJavaFile;
}
}public class Test {
public static void main(String[] args) {
File dir = new File("day08");
printJavaFile(dir);
} public static void printJavaFile(File dir) {
// 获取当前目录下的子文件和子文件夹, 传入过滤器对象
FileFilterImpl fileFilter = new FileFilterImpl();
File[] childFiles = dir.listFiles(fileFilter);
// 现在数组中只有.java文件和子目录
for (File childFile : childFiles) {
if (childFile.isFile()) {
// 如果是文件, 那肯定是.java文件, 直接打印即可
System.out.println(childFile);
} else {
// 如果是目录, 仍然是递归调用
printJavaFile(childFile);
}
}
}
}
FilenameFilter文件过滤器的使用和Lambda优化知识点:
FileFilter和FilenameFilter都是接口, 抽象方法只有一个, 能否使用Lambda表达式优化
5分钟练习: 使用Lambda表达式优化搜索代码java
java.io.FilenameFilter接口: 将File对象拆分为父路径和子路径来判断的过滤器
boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入
dir: 被找到的文件所在的目录 (父路径)
name: 文件的名称 (子路径)
new File(dir, name)需求:
使用File[] listFiles(FilenameFilter filter)方法和Lambda表达式, 将当前模块下的.java文件过滤打印出来
代码:java
public class Test {
public static void main(String[] args) {
File dir = new File("day08");
printJavaFile(dir);
} public static void printJavaFile(File dir) {
// 获取当前目录下的子文件和子文件夹, 传入过滤器对象 // 匿名内部类方式
/*File[] childFiles = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".java");
}
});*/ // Lambda标准格式
/*File[] childFiles = dir.listFiles((File d, String name) -> {
return new File(d, name).isDirectory() || name.toLowerCase().endsWith(".java");
});*/ // Lambda省略格式
File[] childFiles = dir.listFiles((d, name) -> new File(d, name).isDirectory() || name.toLowerCase().endsWith(".java"));
// 现在数组中只有.java文件和子目录
for (File childFile : childFiles) {
if (childFile.isFile()) {
// 如果是文件, 那肯定是.java文件, 直接打印即可
System.out.println(childFile);
} else {
// 如果是目录, 仍然是递归调用
printJavaFile(childFile);
}
}
}
}
--- 今日APIjava
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 静态成员变量
static String pathSeparator: 路径分隔符的字符串形式
static char pathSeparatorChar: 路径分隔符的char形式
Windows系统是 分号;
Linux系统是 冒号:
static String separator: 文件名称分隔符的字符串形式
static char separatorChar: 文件名称分隔符的char形式
Window系统是 反斜杠\
Linux系统是 正斜杠/
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean mkdir(): 创建File表示的目录
boolean mkdirs(): 创建File表示的多级目录
// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对象数组
File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器过滤后的File对象数组java.io.FileFilter接口: 用于File对象的过滤器
boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入java.io.FilenameFilter接口:
boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入
今日目标 能够说出File对象的创建方式java
File(String path)
File(String parent, String child)
File(File parent, String child)
能够说出File类获取名称的方法名称java
String getName()
能够说出File类获取绝对路径的方法名称java
String getAbsolutePath()
能够说出File类获取文件大小的方法名称java
long length(): byte大小
只对文件有效
能够说出File类判断是否是文件的方法名称java
boolean isFile()
能够说出File类判断是否是文件夹的方法名称java
boolean isDirectory()
能够辨别相对路径和绝对路径java
绝对路径: 以盘符开头
相对路径: 不以盘符开头
IDEA相对于项目根目录
能够遍历文件夹java
(File dir)File[] files = dir.listFiles();
for (File file : files) {
if (file.isFile()) {
// 对文件处理
} else {
递归调用方法传递file对象
}
}
能够解释递归的含义java
代码: 方法内部调用方法自己思想: 大问题, 拆解成不同的小问题, 小问题继续拆解成不同的小问题, 直到小问题都能解决, 大问题也就迎刃而解
能够使用递归的方式计算5的阶乘java
int jc(int n) {
if (n == 1) {
return 1;
}
return n * jc(n-1);
}
|
|