1、File类
1.1 File类概述
java.io.File类是文件目录和路径的抽象表示,主要用于创建、获取、删除、文件和文件夹,判断文件和文件夹是否存在,遍历文件夹,获取文件大小
file:文件
directory 目录/文件夹
path 路径
成员变量:
static String pathSeparator 与系统有关的路径分隔符
static char pathSeparatorChar 与系统有关的路径分隔符
static String separator 与系统有关的默认名称分隔符 文件名称分隔符
static char separatorChar 与系统有关的默认名称分隔符
public class Demo01File {
public static void main(String[] args) {
System.out.println(File.pathSeparator);
//;Windows的路径分隔符是;Linux是: 源码中是File.pathSeparatorChar+""
System.out.println(File.pathSeparatorChar);//;
System.out.println(File.separator);//
System.out.println(File.separatorChar);//\Windows的路径分隔符是\Linux是/
//路径不能写死,因为可能用在不同系统上
//如:Windows G:\file\a.txt Linux G:/file/a.txt
//写作"G:" + File.separator + “file” + File.separator + “\a.txt”
}
}
1.2 绝对路径和相对路径
绝对路径:完整的路径,从盘符开始
相对路径:相对于当前目录的根路径
注意:路径不区分大小写,路径中的分隔符在Windows中是\,\是转义字符,\代表\,所以在Java中要写\
1.3 File类的三种构造方法
File(String pathname);
pathname是路径字符串名称
路径可以以文件结尾,也可以以文件夹结尾
路径可以是绝对路径,也可以是相对路径
路径可以存在,也可以不存在,只是将路径字符串封装为File对象,不鉴别路径真伪
File(String parent, String child);分为父路径和子路径,可以分别书写改变,使用起来很灵活
File(File parent,String child);
分为父路径和子路径,可以分别书写改变,使用起来很灵活
可以对调用File类的方法对父路径进行变换再和子路径拼接
public class Demo03FileConstructor {
public static void main(String[] args) {
//File(String pathname);
File f1 = new File(“G:\java\idea\advanced-code\day07-code\src\demo01File”);
System.out.println(f1);//G:\java\idea\advanced-code\day07-code\src\demo01File 重写了toString方法 路径存在,打印结果是一个带下划线的链接
File f2 = new File(“G:\java\idea\advanced-code\day07-code\src\demo01File\b.txt”);
System.out.println(f2);//G:\java\idea\advanced-code\day07-code\src\demo01File\b.txt 路径不存在 打印结果是一个字符串
File f3 = new File(“b.txt”);
System.out.println(f3);//b.txt 路径不存在 打印结果是一个字符串
//File(String parent, String child);
File f4 = new File(“c:\”, “a.txt”);
System.out.println(f4);//c:\a.txt
//File(File parent,String child);
File f5 = new File(“c:\”);
File f6 = new File(f5, “hello.java”);
System.out.println(f6);//c:\hello.java
}
}
1.4 File类的四种获取方法
public String getAbsolutePath();
返回该File的绝对路径名字符串 返回构造方法传递的路径的绝对路径形式
public String getPath();
将该File转换为路径名字符串
public String getName();
返回由该File表示的文件或目录的名称
public long length();
返回由该File表示的文件的长度 以字节为单位 文件夹没有大小返回0 若不存在该文件返回0
public class Demo04FileGet {
public static void main(String[] args) {
File f1 = new File(“a.txt”);
//getAbsolutePath();
String s1 = f1.getAbsolutePath();
System.out.println(s1);//G:\java\idea\advanced-code\a.txt
//getAbsolutePath();
String s2 = f1.getPath();
System.out.println(s2);//a.txt 重写的toString方法就是调用了getPath方法
//getName();
File f2 = new File(“G:\java\idea\advanced-code\a.txt”);
String s3 = f2.getName();
System.out.println(s3);//a.txt 返回构造方法传递的字符串的结尾部分 可能是文件或文件夹
File f3 = new File(“G:\java\idea\advanced-code”);
String s4 = f3.getName();
System.out.println(s4);//advanced-code
//length();
File f4 = new File(“H:\图片\壁纸.jpeg”);
System.out.println(f4.length());//399196
File f5 = new File(“F:\idea”);
System.out.println(f5.length());//0 文件夹没有大小
File f6 = new File(“H:\图片\1.jpeg”);
System.out.println(f6.length());//0 文件不存在,返回0
}
}
1.5 File类的三种判断方法
public boolean exists();
此File表示的文件或目录是否实际存在
public boolean isDirectory();
此File表示的是否为目录,判断构造方法传递的路径是否以文件夹结尾 不存在的路径直接返回false
public boolean isFile();
此File表示的是否为文件,判断构造方法传递的路径是否以文件结尾 不存在的路径直接返回false
public class Demo05FileJudge {
public static void main(String[] args) {
//exists方法
File f1 = new File(“G:\java\idea\advanced-code\day07-code\day07-code.iml”);
System.out.println(f1.exists());//true
File f2 = new File(“day07-code\day07-code.iml”);
System.out.println(f2.exists());//true
File f3 = new File(“G:\java\idea\advanced-code\day07-code\1.txt”);
System.out.println(f3.exists());//false
//isDirectory方法 isFile方法
File f4 = new File(“G:\java\idea\advanced-code\day07-code\1.txt”);
System.out.println(f4.isDirectory());//false
System.out.println(f4.isFile());//false
//先判断是否存在,再判断是目录还是文件
if (f4.exists()) {
System.out.println(f4.isDirectory());
System.out.println(f4.isFile());
}
File f5 = new File(“G:\java\idea\advanced-code\day07-code\day07-code.iml”);
if (f5.exists()) {
System.out.println(f5.isDirectory());//false
System.out.println(f5.isFile());//true
}
}
}
1.6 File类的三种创建方法和一种删除方法
public boolean createNewFile();
只能创建文件,不能创建文件夹。
当文件不存在创建返回true,当文件存在不创建返回false。
创建文件的路径必须存在,否则抛出异常。
方法声明时抛出了IOException,调用方法时必须处理异常
public boolean delete();
public boolean mkdir();
只能创建单级空文件夹。创建多级文件夹会返回false
当文件不存在创建返回true,当文件存在不创建返回false。
构造方法传递的路径不存在返回false
public boolean mkdirs();
既可以创建单级文件夹,也可以创建多级文件夹
public class Demo06FileCreateDelete {
public static void main(String[] args) throws IOException {
//createNewFile方法
File f1 = new File(“G:\java\idea\advanced-code\day07-code\1.txt”);
boolean b1 = f1.createNewFile();
System.out.println(b1);//第一次运行时文件不存在创建文件返回true,第二次运行时文件存在不创建文件返回false
File f2 = new File(“G:\java\idea\advanced-code\day07-cod\2.txt”);
boolean b2 = f2.createNewFile();
System.out.println(b2);//路径不存在,抛出异常IOException: 系统找不到指定的路径。
//mkdir方法
File f3 = new File(“G:\java\idea\advanced-code\day07-code\2.txt”);//创建的是一个叫2.txt的文件夹
boolean b3 = f3.mkdir();
System.out.println(b3);//第一次运行时文件夹不存在创建文件夹返回true,第二次运行时文件夹存在不创建文件夹返回false
File f4 = new File(“G:\java\idea\advanced-code\day07-cod\2.txt”);
boolean b4 = f4.mkdir();
System.out.println(b4);//构造方法传递的路径不存在返回false 不会抛出异常
File f5 = new File(“G:\java\idea\advanced-code\day07-code\a\b\c”);
boolean b5 = f5.mkdir();
System.out.println(b5);//创建多级文件夹会返回false
//mkdirs方法
File f6 = new File(“G:\java\idea\advanced-code\day07-code\a\b\c”);
boolean b6 = f6.mkdirs();
System.out.println(b6);//第一次运行时文件夹不存在创建文件夹返回true,第二次运行时文件夹存在不创建文件夹返回false
File f7 = new File(“I:\java\idea\advanced-code\day07-cod\a\b\c”);
boolean b7 = f7.mkdirs();
System.out.println(b7);//构造方法传递的路径盘符不存在返回false 不会抛出异常
File f8 = new File(“G:\java\idea\advanced-code\day07-cod\a\b\c”);
boolean b8 = f8.mkdirs();
System.out.println(b8);//构造方法传递的路径不存在,直接创建不存在的文件夹
//delete方法 删除File表示的目录或文件 直接从硬盘删除,不经过回收站 文件夹中有内容不会删除返回false,多级文件夹要一层一层删除 构造方法中路径不存在返回false
File f9 = new File(“G:\java\idea\advanced-code\day07-cod”);
boolean b9 = f8.delete();
System.out.println(b9);
File f10 = new File(“G:\java\idea\advanced-code\day07-code\1.txt”);
boolean b10 = f6.delete();
System.out.println(b10);
}
}
1.7 File类的遍历目录的方法
public String[] list();返回一个String数组,包括File目录中的所有子文件和目录
public File[] listFiles();返回一个File数组,包括File目录中的所有子文件和目录
可以获取到隐藏文件和隐藏文件夹
遍历的的都是构造方法中的路径,若构造方法中的路径不存在或不是一个目录,会抛出空指针异常
public class Demo07FileErgodic {
public static void main(String[] args) {
//list方法
File f1 = new File(“G:\java\idea\advanced-code\day07-code”);
String[] list1 = f1.list();
for (String s : list1) {
System.out.println(s);//day07-code.iml
//src
}
File f2 = new File(“G:\java\idea\advanced-code\day07-cod”);//路径不存在,抛出NullPointerException空指针异常
String[] list2 = f2.list();
for (String s : list2) {
System.out.println(s);
}
File f3 = new File(“G:\java\idea\advanced-code\day07-code\day07-code.iml”);//路径不是一个目录,抛出NullPointerException空指针异常
String[] list3 = f3.list();
for (String s : list3) {
System.out.println(s);
}
//listFiles方法
File f4 = new File(“G:\java\idea\advanced-code\day07-code”);
File[] files1 = f4.listFiles();
for (File file : files1) {
System.out.println(file);//打印File对象,相当于调用重写的toString方法
//G:\java\idea\advanced-code\day07-code\day07-code.iml
//G:\java\idea\advanced-code\day07-code\src
}
}
}
2、递归
2.1 递归概述
直接递归:自己调用自己
间接递归:自己调用别人,别人再调用自己
注意:
(1)要有条件限定,保证递归可以停止,否则会栈内存溢出 StackOverflowError
(2)即使有条件限定,递归次数也不能太多,否则会栈内存溢出
(3)构造方法禁止递归,因为构造方法是用来创建对象的,一直递归会导致内存中有无数个对象,会直接编译报错
public class Demo01Recursion {
public static void main(String[] args) {
//a();//StackOverflowError
b(1);//StackOverflowError
}
public Demo01Recursion() {
//Demo01Recursion();//构造方法禁止递归
}
//a方法没有条件限定
public static void a() {
System.out.println(“a方法”);
a();
}
//b方法有条件限定但递归次数太多
public static void b(int i) {
System.out.println(i);
if (i == 20000) {
return;
}
b(++i);
}
}
2.2 递归计算1-n的和
注意:main方法调用calculate方法,calculate方法调用calculate方法,导致内存中有无数个calculate方法,这需要频繁地创建方法,调用方法,销毁方法,使得效率低下。计算1-n的和,推荐使用for循环即可。
public class Demo02CalculateNSum {
public static void main(String[] args) {
int sum = 0;
sum = calculate(10);//main方法调用calculate方法
System.out.println(sum);
}
public static int calculate(int n) {
if (n == 1) {
return 1;//return之后就弹出栈内存,方法结束
}
return n + calculate(n - 1);//calculate方法一直调用calculate方法,直到n等于1,就将1返回给上一个调用自己的calculate方法,一直向上传递返回值,直到n等于n
}
}
2.3 递归计算n阶乘
public class Demo03NFactorial {
public static void main(String[] args) {
int sum = 0;
sum = calculate(6);
System.out.println(sum);
}
public static int calculate(int n) {
if (n == 1) {
return 1;
}
return n * calculate(n-1);
}
}
2.4 递归打印多级目录
public class Demo04RecursionFile {
public static void main(String[] args) {
File file = new File(“G:\java\idea\advanced-code\day07-code”);
printFile(file);
}
public static void printFile(File file) {
System.out.println(file);//先打印传递的文件夹路径
File[] filelist = file.listFiles();
for (File f : filelist) {
if (f.isDirectory()) {//判断f是否为文件夹
printFile(f);//f是文件夹,递归调用本函数传递f
} else {
System.out.println(f);//f不是文件夹,打印到文件f的路径就可以
}
}
}
}
2.5 递归搜索特定后缀名的文件
public class Demo05FindFile {
public static void main(String[] args) {
File file = new File(“G:\java\idea\advanced-code\day07-code”);
findFiles(file);
}
public static void findFiles(File file) {
File[] listfiles = file.listFiles();
for (File f : listfiles) {
if (f.isDirectory()) {//判断f是否为目录
findFiles(f);//f为目录则递归调用本函数获取f的子文件夹或子文件
} else {
if (f.getName().toLowerCase().endsWith(".java")) {
//getName获取File对象对应文件或文件夹的名称,即字符串结尾部分,包括后缀名
//toLowerCase方法将获取到的文件名转换为小写,防止搜索不到后缀为对应大写(.JAVA)的文件
//String类的endWith方法获取字符串的文件的后缀名
System.out.println(f);
}
}
}
}
}
2.6 文件过滤器
File类中有两个和listFiles重载的方法,方法的参数就是过滤器
listFiles();
File[] listFiles(FileFilter filter);
File[] ListFiles(FilenameFilter filter);
FileFilter是一个接口,用于过滤文件(File对象),只有一个方法
boolean accept(File pathname);
FilenameFilter也是一个接口,用于过滤文件名称,只有一个方法
boolean accept(File dir, String name);
注意:
这两个过滤器接口没有实现类,需要我们自己写实现类,重写accept方法,定义过滤规则
使用FileFilter接口的实现类文件创建对象、匿名内部类和lambda来递归搜索特定后缀名的文件
FileFilter接口实现类
public class FileFilterImpl implements FileFilter {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
//如果该File对象是一个文件夹,也返回true,将其存入File对象数组,继续遍历
return true;
}
//以.java结尾返回true,否则返回false
return pathname.getName().toLowerCase().endsWith(".java");
}
}
测试类
public class Demo06FileFilter {
public static void main(String[] args) {
File file = new File(“G:\java\idea\advanced-code\day07-code”);
printFile(file);
}
public static void printFile(File file) {
//System.out.println(file);
//法一,使用创建的实现类文件
//这里的listFiles方法做了三件事:
//1、将File对象file的构造方法中传递的目录进行遍历,获取目录中的文件夹/文件,封装为File对象
//2、调用参数传递的FileFilter实现类FileFilterImpl的accept方法
//3、把遍历得到的每一个File对象,传递给accept方法的参数pathname
//如果File对象传递过去到accept方法,返回true,就会将该File对象存进File对象数组,返回false,就不存进File对象数组
File[] listfiles = file.listFiles(new FileFilterImpl());
//法二,使用匿名内部类
File[] listfiles2 = file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".java");
}
});
//法三,使用lambda(接口中有且只有一个抽象方法)
File[] listfiles3 = file.listFiles((File pathname) -> {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".java");
});
for (File f : listfiles2) {
if (f.isDirectory()) {
printFile(f);
} else {
System.out.println(f);
}
}
}
}
2.7 FilenameFilter过滤器的使用
使用FilenameFilter接口的实现类文件创建对象、匿名内部类和lambda来递归搜索特定后缀名的文件
public class Demo07FilenameFilter {
public static void main(String[] args) {
File file = new File(“G:\java\idea\advanced-code\day07-code”);
printFile(file);
}
public static void printFile(File file) {
//法一,使用匿名内部类
File[] listfiles = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
//利用File类的构造方法将路径和文件名组合成一个File对象,判断其是否为文件夹
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".java");
}
});
//法二,使用lambda(接口中有且只有一个抽象方法)
File[] listfiles2 = file.listFiles((dir, name) -> {
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".java");
});
//通过过滤器得到的File对象数组中的File对象要么是文件夹,要么是以java结尾的文件
for (File f : listfiles2) {
if (f.isDirectory()) {
printFile(f);
} else {
System.out.println(f);
}
}
}
}