今天我们进入java中IO的学习,File类可以操作磁盘上的文件,递归是常用的一种思想,把无法解决的大问题拆分成容易解决的小问题。
以下是今天的学习目标:
- 能够说出File对象的创建方式
- 能够说出File类获取名称的方法名称
- 能够说出File类获取绝对路径的方法名称
- 能够说出File类获取文件大小的方法名称
- 能够说出File类判断是否是文件的方法名称
- 能够说出File类判断是否是文件夹的方法名称
- 能够辨别相对路径和绝对路径
- 能够遍历文件夹
- 能够解释递归的含义
- 能够使用递归的方式计算5的阶乘
- 能够说出使用递归会内存溢出隐患的原因
以下是今天的详细笔记:
File类File类概述java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
我们可以对File进行的操作:
创建文件/目录
删除文件/目录
获取文件/目录
判断文件/目录是否存在
对目录进行遍历
获取文件的大小
重要英文单词的含义: (起变量名时会用到)
file: 文件
directory: 目录
path: 路径
File类的静态成员变量
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 静态成员变量
static String pathSeparator: 路径分隔符的字符串形式
static char pathSeparatorChar: 路径分隔符的char形式
Windows系统是 分号;
Linux系统是 冒号:
static String separator: 文件名称分隔符的字符串形式
static char separatorChar: 文件名称分隔符的char形式
Window系统是 反斜杠\
Linux系统是 正斜杠/
绝对路径和相对路径
绝对路径:
以盘符开始的路径
如: "D:\\a\\hi.txt"
相对路径:
不以盘符开始的简化路径. 相对于项目的根目录
如: "a\\1.mp3", "123.txt"
注意事项:
1. 路径不区分大小写 (在Windows系统中不区分大小写, Linux, Mac区分)
2. 路径一般写成字符串, 而字符串中一个\是转义, 所以要写两个\\
File类: 构造方法
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
5分钟练习: 测试构造方法
需求:
测试File类的构造方法:
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 File(String pathname): 根据 路径字符串 封装一个File对象
File f1 = new File("z:\\z.txt"); // 不存在的路径也可以创建File对象
System.out.println(f1);
// File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File f2 = new File("a\\", "a.txt"); // 相对路径也可以
System.out.println(f2);
// File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
File f3 = new File(new File("d:\\"), "d.txt");
System.out.println(f3);
// 创建File对象后, 并不会在磁盘上创建文件或目录!
}
}
File类: 获取方法
java.io.File类
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
5分钟练习: 测试获取方法
需求:
测试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("a.txt");
System.out.println(f1.getAbsolutePath()); // File对象是相对路径, 该方法可以获取到绝对路径
// String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
System.out.println(new File("a.txt").getPath()); // 创建对象时是什么路径, 获取的就是什么
System.out.println(new File("d:\\a.txt").getPath());
// String getName(): 获取File对象的文件名或目录名
File f3 = new File("a\\b\\c\\d.txt");
System.out.println(f3.getName());
// long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
File f4 = new File("day08\\src\\com\\itheima\\test02\\Test.java"); // 相对路径
System.out.println(f4.length()); // 1431
}
}
File类: 判断方法
java.io.File类
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
5分钟练习: 测试判断方法
需求:
测试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\\src");
System.out.println(f1.exists());
// boolean isDirectory(): 判断File表示的是否为目录
File f2 = new File("day08\\src\\com\\itheima\\test03");
System.out.println(f2.isDirectory());
// boolean isFile(): 判断File表示的是否为文件
File f3 = new File("day08\\src\\com\\itheima\\test03\\Test.java");
System.out.println(f3.isFile());
}
}
File类: 创建删除方法
java.io.File类
// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean mkdir(): 创建File表示的目录
boolean mkdirs(): 创建File表示的多级目录
5分钟练习: 测试创建删除方法
需求:
在当前的模块中创建a目录(注意用相对路径时加上模块名), 在a目录中创建b目录
然后在b目录中创建b.txt文件和c.txt文件
删除c.txt文件
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) throws IOException {
// 在当前的模块中创建a目录
/* File dirA = new File("day08\\a");
dirA.mkdir();
// 在a目录中创建b目录
File dirB = new File("day08\\a\\b");
dirB.mkdir();*/
// 以上两步可以合并为一步
File dirAB = new File("day08\\a\\b");
dirAB.mkdirs();
// 在b目录中创建b.txt文件和c.txt文件
File fileB = new File("day08\\a\\b\\b.txt");
fileB.createNewFile();
File fileC = new File("day08\\a\\b\\c.txt");
fileC.createNewFile();
// 删除c.txt文件
fileC.delete();
boolean result = new File("z:\\a").mkdirs(); // 磁盘不存在, 不会创建
System.out.println(result); // false
}
}
File类: 遍历目录方法
java.io.File类
// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
注意:
只能用表示目录的File对象调用
用文件的File对象, 或者路径不存在, 调用会报错
5分钟练习: 测试遍历目录方法
需求:
利用listFiles()遍历目录方法, 将当前模块中的文件或目录打印出来
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// 创建File对象指向当前模块
File module = new File("day08");
// listFiles()获取当前目录中的子文件和子目录的File数组
File[] files = module.listFiles();
for (File file : files) {
System.out.println(file);
}
// list(): 获取当前目录中的子文件和子目录的文件名数组
String[] list = module.list();
for (String s : list) {
System.out.println(s);
}
}
}
递归递归的概念, 分类, 注意事项
递归思想:
遇到一个问题时, 将该问题拆解成可以解决的小问题, 如果解决不了, 继续拆解为更小的问题. 如果小问题解决了, 大问题也就能够解决
Java中实现递归的方式:
方法内部调用方法自己 (所以必须定义方法)
递归的分类:
直接递归: 方法自己调用方法
间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法
递归时的注意事项:
1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出
2. 递归次数不能太多, 否则会栈内存溢出
3. 构造方法不能递归
递归的使用前提:
调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归
练习: 递归计算1~n的和5分钟练习: 递归求和
需求: 求1~n的和 1~5 1+2+3+4+5
分析:
求1~5的和: 5+4+3+2+1
5~1的和 = 5 + (4~1的和)
4~1的和 = 4 + (3~1的和)
3~1的和 = 3 + (2~1的和)
2~1的和 = 2 + (1~1的和)
1~1的和 = 1;
把解决不了的问题, 定义成方法 (定义方法求5~1的和)
如果小问题能解决, 直接写代码实现
如果小问题不能解决, 就递归调用方法实现
求1~n的和: n+(n-1)+...+2+1
n~1的和 = n + ((n-1)~1的和)
(n-1)~1的和 = (n-1) + ((n-1-1)~1的和)
...
2~1的和 = 2 + (1~1的和)
1~1的和 = 1;
递归实现思路
将要解决的问题, 封装为方法
求1~n的和: 定义方法
getSum(n);
getSum(n-1)
getSum(1);
private static int getSum(int n) { // 解决问题: 求n~1的和
// 出口(方法自己不再调用自己)
if (n == 1) {
return 1;
}
return n + getSum(n-1);
}
在方法内部, 拆解问题, 不能解决的小问题, 继续递归调用方法
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
int sum1 = sum(3); // 6
int sum2 = sum(5); // 15
System.out.println(sum1);
System.out.println(sum2);
}
// 定义方法: 求n到1的和
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 乘积需求: 使用递归计算5的阶乘分析: 5! = 5* 4*3*2*1 5* 4! 4! = 4* 3! 3! = 3* 2! 2! = 2* 1! 1! = 1 问题全都解决 n! = n* (n-1)! (n-1)! = n-1 * (n-2)! ... 2! = 2* 1! 1! = 1 问题全都解决 递归实现思路 将要解决的问题, 封装为方法 求n的阶乘 [Java] 纯文本查看 复制代码 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
}
// 计算n的阶乘
public static int jc(int n) {
// 出口
if (n == 1) {
return 1; // 能解决问题, 直接写代码
}
// 如果不能解决, 则拆解问题
return n * jc(n-1);
}
} 练习: 递归打印多级目录5分钟练习: 递归打印多级目录
需求: 打印当前模块目录下的所有文件和目录路径 (包含子目录)
aaa/
|_ bbb/
| | ccc/
| | |_ c1.java
| |
| |_ b1.java
| |_ b2.java
|
|_ a1.java
|_ a2.java
递归思想拆分问题:
大问题:
打印aaa目录中子文件和子目录的路径 =
打印a1,a2子文件路径
&& 打印bbb子目录路径
&& 打印bbb子目录中子文件和子目录的路径?
打印bbb子目录中子文件和子目录的路径 =
打印b1,b2子文件路径
&& 打印ccc子目录路径
&& 打印ccc子目录中子文件和子目录的路径?
打印ccc子目录中子文件和子目录的路径 =
打印b1,b2子文件路径
出口? 一个目录中不再有子目录
要定义的方法: 打印某个目录中子文件和子目录的路径
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
File dir = new File("day08");
print(dir);
}
// 定义方法: 打印某个目录中所有路径
public static void print(File dir) { // 传入要打印的目录的File对象
// 先打印当前目录的路径
System.out.println(dir);
// 获取当前目录中的所有子文件和子目录
File[] files = dir.listFiles();
// 遍历数组
for (File file : files) {
// file代表子文件或者子目录, 具体是什么还需要判断
if (file.isFile()) {
// 如果是文件, 则打印文件
System.out.println(file);
} else {
// 如果是目录, 则递归调用当前方法, 打印"该子目录"中的所有路径
print(file); // 注意传入的是子目录对象!!!!!
}
}
}
}
综合案例综合案例之多级目录搜索5分钟练习: 递归遍历多级目录
补充String类中的方法:
boolean endsWith(String suffix): 判断字符串是否以指定的字符串结尾
String toLowerCase(): 将字符串转为小写字母
String s = "AAAaaa".toLowerCase();
s: "aaaaaa"
aaa.java 文件名
file.getName() boolean b = "aaa.java".endsWith(".java");
需求: 打印当前模块中的.java文件 (包含子目录)
aaa/
|_ bbb/
| | ccc/
| | |_ c1.java
| |
| |_ b1.java
| |_ b2.txt
|
|_ a1.java
|_ a2.txt
递归思想分析:
大问题: 打印aaa目录下的所有java文件路径 = 打印a1.java && 打印bbb目录下的所有java文件路径?
打印bbb目录下的所有java文件路径 = 打印b1.java && 打印ccc目录下的所有java文件路径?
打印ccc目录下的所有java文件路径 = 打印c1.java
出口? 某个目录下不再有子目录
定义方法: 打印某个目录下所有java文件路径
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
print(new File("day08"));
}
// 定义方法: 打印某个目录中的.java文件
public static void print(File dir) {
// 先获取当前目录中的所有文件
File[] files = dir.listFiles();
// 遍历
for (File file : files) {
// 判断是文件还是目录
if (file.isFile()) {
// 是文件, 判断后缀
if (file.getName().toLowerCase().endsWith(".java")) {
// 是java文件, 打印
System.out.println(file);
}
} else if (file.isDirectory()) {
// 是目录, 递归调用方法
print(file);
}
}
}
}
FileFilter文件过滤器的原理和使用
java.io.File类: Filter过滤器
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则不加入
5分钟练习: 使用FileFilter
需求:
使用File[] listFiles(FileFilter filter)方法, 将当前模块中的.java文件过滤出来, 打印到控制台
代码:
[Java] 纯文本查看 复制代码 public class JavaFileFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
// 如果是目录, 则加入结果
if (pathname.isDirectory()) {
return true;
}
// 如果不是目录, 则判断以.java结尾的也加入结果
return pathname.getName().toLowerCase().endsWith(".java");
}
}
public class Test {
public static void main(String[] args) {
print(new File("day08"));
}
// 打印指定目录中的.java文件
public static void print(File dir) {
// 获取当前目录中的所有符合要求的文件, 传递文件过滤器
File[] files = dir.listFiles(new JavaFileFilter());
// 遍历
for (File file : files) {
if (file.isFile()) {
// 如果是文件, 则直接打印, 因为已经过滤好了
System.out.println(file);
} else if (file.isDirectory()) {
// 如果是目录, 则递归调用方法打印内部的java文件
print(file);
}
}
}
}
FileFilter文件过滤器的使用和Lambda优化
5分钟练习: 使用Lambda表达式优化搜索代码需求:
使用File[] listFiles(FilenameFilter filter)方法和Lambda表达式, 将当前模块下的.java文件过滤打印出来
代码:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
print(new File("day08"));
}
// 打印指定目录中的.java文件
public static void print(File dir) {
// 获取当前目录中的文件, 使用过滤器
/*File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".java");
}
});*/
// 使用Lambda表达式简化
File[] files = dir.listFiles((d, name) -> new File(d, name).isDirectory() || name.toLowerCase().endsWith(".java"));
// 遍历
for (File file : files) {
if (file.isFile()) {
// 是文件, 则打印
System.out.println(file);
} else if (file.isDirectory()) {
// 是目录, 则递归
print(file);
}
}
}
}
今日API
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则不加入
|
|