# File类
# File类的概述
java.io.File
类是文件和目录路径名的抽象表示形式。java把电脑中的文件和目录封装成了一个File
类,我们可以使用File
类对文件和文件夹进行操作:
- 创建一个文件或文件夹
- 删除一个文件或文件夹
- 获取一个文件或文件夹
- 判断一个文件或文件夹
- 对文件夹进行遍历
- 获取文件的大小
File
类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法。在File
类中,有三个重要概念:
file
:文件directory
:文件夹/目录path
:路径
# File类的静态成员变量
静态成员变量 | 说明 |
---|---|
File.pathSeparator | 与系统有关的路径分隔符,为了方便表示为字符串 |
File.pathSeparatorChar | 与系统有关的路径分隔符 |
File.separator | 与系统有关的默认名称分隔符,为了方便表示为字符串 |
File.separatorChar | 与路径有关的路径分隔符 |
- 默认情况下,windows系统的默认路径分隔符为
;
,linux系统默认路径分隔符为:
。 - 默认情况下,windows系统的默认名称分隔符为
\
,linux系统默认名称分隔符为/
。
# 绝对路径和相对路径
路径不区分大小写,可以分为两种路径:绝对路径和相对路径
- 绝对路径:是一个完整的路径,以盘符开始的路径。
- 相对路径:是一个简化的路径,相对于当前项目的根目录,如果使用当前项目的根目录,则路径可以简化。
# File类的构造方法
File(String pathname)
:通过将给定路径名字符串转换为抽象路径名来创建一个新File实例。参数 说明 String pathname
String pathname
:字符串的路径名称
路径可以是以文件结尾或文件夹结尾
路径可以是相对路径或绝对路径
路径可以是存在或不存在
创建File对象,只是把字符串路径封装为File
对象,不考虑路径的真假情况File(String parent, String child)
:根据parent路径名字字符串和child路径名字字符串创建了一个新File实例。
参数 | |
---|---|
String parent, String child | 把路径分成了两部分String parent :父路径String child :子路径好处: 父路径和子路径,可以单独书写,使用起来灵活;父子路径都可以变化 |
File(File parent, String child)
:根据parent抽象路径和child路径名字字符串创建一个新File实例。参数 File parent, String child
把路径分成了两部分
File parent
:父路径
String child
:子路径
好处:
父路径和子路径,可以单独书写,使用起来灵活;父路径和子路径都可以变化
父路径是File
类型,可以使用File
的方法对路径进行一些操作再使用路径创建对象
# File类获取功能
public String getAbsolutePath()
:返回此File的绝对路径名字符串,获取构造方法中传递的路径,无论是绝对路径还是相对路径,返回的都是绝对路径。public String getPath()
:将此File转换为路径名字符串,即获取构造方法中传递的路径,传递的路径是什么样就返回什么样的路径。public String getName()
:返回由此File表示的文件或文件夹(目录)的名称,获取的就是构造方法传递路径的结尾部分(文件,文件夹)public long length()
:返回由此File表示的文件的长度(大小),获取的构造方法指定的文件的大小,以字节为单位。注意,文件夹是没有大小概念的,不能获取文件夹大小。如果构造方法中给出的路径不存在,那么length方法返回零。
# File判断功能
public boolean exists()
:此File表示的文件或目录是否实际存在。用于判断构造方法中的路径是否存在,存在则为true,不存在则为false。public boolean isDirectory()
:用于判断构造方法中给定的路径是否以文件夹结尾。如果是返回true,否则返回falsepublic boolean isFile()
:此File
表示的是否为文件,用于判断构造方法中给定的路径是否以文件结尾。如果是返回true,否则返回false。
isDirectory()
和isFile()
使用的前提是路径必须存在,否则都返回false。由于电脑中只有文件或文件夹,因此,这两个方法是互斥的。
# File类创建删除功能
public boolean createNewFile()
:当且仅当具有该名称的文件不存在时,创建一个新的空文件。说明 注意事项 当且仅当具有该名称的文件不存在时,创建一个新的空文件。
创建文件的路径和名称在构造方法中给出,
返回值:
true,文件不存在,创建文件返回true;
false,文件存在,不会创建此方法只能创建文件,不能创建文件夹,
创建文件的路径必须存在,否则会抛出异常。public boolean delete()
:删除由此File
表示的文件或目录。说明 注意事项 此方法可以删除构造方法路径中给出的文件/文件夹
返回值:
true:文件/文件夹删除成功;
false:文件夹中有内容,不会删除,返回false;构造方法中路径不存在false;该方法是直接在硬盘删除文件/文件夹,不走回收站,删除要谨慎。 public boolean mkdir()
:创建由此File
表示的目录。说明 注意事项 创建文件夹的路径和名称在构造方法中给出,
返回值:
true,文件夹不存在,创建文件夹返回true;
false,文件夹存在,不会创建;构造方法中给出的路径不存在返回false此方法只能创建文件夹,不能创建文件 public boolean mkdirs()
:创建由此File
表示的目录,包括任何必须但不存在的父目录
# File类目录的遍历功能
File
类遍历目录(文件夹)的方法有两个:
public String[] list()
:返回一个String
数组,表示该File
目录中的所有子文件或目录。public File[] listFiles()
:返回一个File
数组,表示该File
目录中的所有子文件或目录。说明 list()
和listFiles()
遍历的是构造方法中给出的目录,
如果构造方法给出的目录的路径不存在,会抛出空指针异常。
如果构造方法给出的路径不是一个目录,也会抛出空指针异常。
# 递归
# 递归的定义
指在当前方法中自己调用自己的情况
# 递归的分类
递归分为两种:直接递归和间接递归
- 直接递归:方法直接调用自己
- 间接递归:A方法调用B方法,B方法调用C方法,C方法调用A方法,这种不直接调用自己的递归,称为间接递归。
# 递归的注意事项
- 递归一定要有一定的条件限定,保证递归能够停下来,否则会发生栈内存溢出。
- 在递归中虽然有限定条件,但是递归的次数不宜过多,否则也会发生栈内存溢出。
- 构造方法,要禁止递归。
# 递归遍历多级目录
为了更好理解递归,我们选定目录E:\文档
,遍历其子目录及文件。
package com.example.demo;
import java.io.File;
public class FileListDemo {
public static void main(String[] args) {
File file = new File("E:\\文档");
getAllFiles(file);
}
public static void getAllFiles(File dir) {
System.out.println(dir);
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
getAllFiles(file); //递归调用
} else {
System.out.println(file);
}
}
}
}
# 递归遍历特定文件搜索
在这个例子中,我们需要递归搜索以.pdf
结尾的文件,因此,我们在else
语句中增加判断是否以.pdf
结尾的文件,再打印输出。
package com.example.demo;
import java.io.File;
public class FileListDemo {
public static void main(String[] args) {
File file = new File("E:\\文档");
getAllFiles(file);
}
public static void getAllFiles(File dir) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
getAllFiles(file);
} else {
if(file.getName().endsWith(".pdf")){
System.out.println(file);
}
}
}
}
}
# 文件过滤器接口
在File
类中有两个和listFiles
重载的方法,方法的参数传递的就是过滤器。
# FileFilter过滤器接口
使用FileFilter
过滤器重载的方法为File[] listFiles(FileFilter filter)
,过滤器的详情如下:
方法 | 作用 | 参数 |
---|---|---|
File[] listFiles(FileFilter filter) | 它是用于抽象路径名(File对象)的过滤器,主要作用是, 用来过滤文件(File对象) | FileFilter 接口内部包含一个boolean accept(File pathname) ,测试抽象路径名是否包含在某个路径名列表,其参数是使用listFiles 方法遍历目录得到的每一个文件对象。 |
其中,listFiles
方法一共做了两件事:
listFiles
方法会对构造方法中传递的目录进行遍历,获取目录中的每一个文件/文件夹,并封装为File
对象。listFiles
方法会调用参数传递的过滤器中的方法accept
。listFiles
方法会把遍历得到的每一个File
对象,传递给accept
方法的参数pathname
。
当accept
方法返回true时,listFiles
方法就将该File
对象添加到返参的File
数组里。否则,不添加到返参的File
数组里。
# FilenameFilter过滤器接口
方法 | 作用 | 参数 |
---|---|---|
File[] listFiles(FilenameFilter filter) | 它的作用是用于过滤文件名 | 其内部包含boolean accept(File dir,String name) 测试指定文件是否包含在某一文件列表中,File dir 是构造方法中传递的被遍历的目录,String name 是使用listFiles 方法遍历目录获取的每一个文件/文件夹名称 |
注意:两个过滤器接口都没有实现类,需要自行编写实现类,重写过滤的方法accept
,在方法中自己定义过滤的规则。
# 使用FileFiter过滤器重写文件搜索
首先,我们需要实现FileFilter
接口,重写其accept
方法。在这个过滤方法中,对于目录我们直接返回true,让其在下一段代码中继续遍历其中的文件,对于文件,则判断是否是以.pdf
结尾。
package com.example.demo;
import java.io.File;
import java.io.FileFilter;
public class FileFilterImpl implements FileFilter {
@Override
public boolean accept(File pathname) {
// 如果pathname是一个文件夹,则返回true,继续遍历文件夹
if(pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".pdf");
}
}
接着,我们将FileFilterImpl
实现类作为参数传递给listFiles
方法。
package com.example.demo;
import java.io.File;
public class FileFiterDemo {
public static void main(String[] args) {
File file = new File("E:\\文档");
getAllFiles(file);
}
public static void getAllFiles(File dir) {
File[] files = dir.listFiles(new FileFilterImpl());
for (File file : files) {
if (file.isDirectory()) {
getAllFiles(file);
} else {
System.out.println(file);
}
}
}
}
运行程序,我们成功搜索出.pdf
结尾的文件。
# 使用FilenameFilter过滤器重写文件搜索
下面,我们继续使用FilenameFilter
来完成文件搜索功能。这次,我们使用匿名内部类,逻辑和刚才一致。
package com.example.demo;
import java.io.File;
import java.io.FilenameFilter;
public class FilenameFilterDemo {
public static void main(String[] args) {
File file = new File("E:\\文档");
getAllFiles(file);
}
public static void getAllFiles(File dir) {
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// 判断其是否是文件夹或者其是否以.pdf结尾
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".pdf");
}
});
for (File file : files) {
if (file.isDirectory()) {
getAllFiles(file);
} else {
System.out.println(file);
}
}
}
}
类似地,可以使用匿名内部类代替原有的FileFilter
实现方法。
# 使用Lambda表达式实现文件搜索
在JDK8中,我们可以使用Lambda表达式简化代码,将上面代码中的这段代码
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// 判断其是否是文件夹或者其是否以.pdf结尾
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".pdf");
}
});
简化为:
File[] files = dir.listFiles((d,name)-> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".pdf"));
其完整实现如下:
package com.example.demo;
import java.io.File;
import java.io.FilenameFilter;
public class FilenameFilterLDemo {
public static void main(String[] args) {
File file = new File("E:\\文档");
getAllFiles(file);
}
public static void getAllFiles(File dir) {
File[] files = dir.listFiles((d,name)-> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".pdf"));
for (File file : files) {
if (file.isDirectory()) {
getAllFiles(file);
} else {
System.out.println(file);
}
}
}
}