- 能够说出File对象的创建方式
- 能够说出File类获取名称的方法名称
- 能够说出File类获取绝对路径的方法名称
- 能够说出File类获取文件大小的方法名称
- 能够说出File类判断是否是文件的方法名称
- 能够说出File类判断是否是文件夹的方法名称
- 能够辨别相对路径和绝对路径
- 能够遍历文件夹
- 能够解释递归的含义
- 能够使用递归的方式计算5的阶乘
- 能够说出使用递归会内存溢出隐患的原因
概述
java.io.File
类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法。
1. 静态成员变量
static String pathSeparator
:与系统有关的路径分隔符,为了方便,它被表示为一个字符串。static char pathSeparatorChar
:与系统有关的路径分隔符。static String separator
: 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。static char separatorChar
:与系统有关的默认名称分隔符。
import java.io.File;
public class Demo01File {
public static void main(String[] args) {
String pathSeparator = File.pathSeparator;
System.out.println(pathSeparator); // 路径分隔符 windows:分号; linux:冒号:
System.out.println(File.pathSeparatorChar);
String separator = File.separator;
System.out.println(separator); // 文件名称分隔符 windows:反斜杠\ linux:正斜杠/
System.out.println(File.separatorChar);
}
}
结果:
;
;
\
\
注意
- 一个File对象代表硬盘中实际存在的一个文件或者目录。
- 无论该路径下是否存在文件或者目录,都不影响File对象的创建。
操作路径
- 路径不能写死了
C:\develop\a\a.txt windows
C:/develop/a/a.txt linux "C:"+File.separator+"develop"+File.separator+"a"+File.separator+"a.txt"
2. 构造方法
第一种
- 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
public File(String pathname);
参数:字符串的路径名称
路径要求
- 路径可以是以文件结尾,也可以是以文件夹结尾
- 路径可以是相对路径,也可以是绝对路径
- 路径可以是存在,也可以是不存在
- 创建File对象,只是把字符串路径封装为File对象,不考虑路径的真假情况
举例:
// 文件路径名
String pathname = "D:\\aaa.txt";
File file1 = new File(pathname);
// 文件路径名
String pathname2 = "D:\\aaa\\bbb.txt";
File file2 = new File(pathname2);
第二种
- 从父路径名字符串和子路径名字符串创建新的 File实例。
public File(String parent, String child);
参数
把路径分成了两部分
- String parent:父路径
- String child:子路径
好处
父路径和子路径,可以单独书写,使用起来非常灵活;父路径和子路径都可以变化
举例:
// 通过父路径和子路径字符串
String parent = "d:\\aaa";
String child = "bbb.txt";
File file3 = new File(parent, child);
第三种
- 从父抽象路径名和子路径名字符串创建新的 File实例。
public File(File parent, String child);
参数
把路径分成了两部分
-
File parent:父路径
-
String child:子路径
好处
-
父路径和子路径,可以单独书写,使用起来非常灵活;父路径和子路径都可以变化
-
父路径是File类型,可以使用File的方法对路径进行一些操作,再使用路径创建对象
举例:
// 通过父级File对象和子路径字符串
File parentDir = new File("d:\\aaa");
String child = "bbb.txt";
File file4 = new File(parentDir, child);
3. 常用方法
获取方法
绝对路径
-
返回此File的绝对路径名字符串
获取的构造方法中传递的路径,无论路径是绝对的还是相对的,
getAbsolutePath
方法返回的都是绝对路径
public String getAbsolutePath();
相对路径
- 将此File转换为路径名字符串。
public String getPath();
绝对路径和相对路径
- 绝对路径:从盘符开始的路径,这是一个完整的路径。如:`` c:\111\a.txt`
- 相对路径:相对于项目目录的路径,这是一个便捷的路径。如:
c:\\111
注意
- 路径是不区分大小写
- 路径中的文件名称分隔符windows使用反斜杠
- 反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠
代码:
public class FilePath {
public static void main(String[] args) {
// D盘下的bbb.java文件
File f = new File("D:\\bbb.java");
System.out.println(f.getAbsolutePath());
// 项目下的bbb.java文件
File f2 = new File("bbb.java");
System.out.println(f2.getAbsolutePath());
}
}
结果:
D:\bbb.java
D:\idea_project_test4\bbb.java
文件/目录名
-
返回由此File表示的文件或目录的名称。
获取的就是构造方法传递路径的结尾部分(文件/文件夹)
public String getName();
文件长度
-
返回由此File表示的文件的长度。
获取的是构造方法指定的文件的大小,以字节为单位,
length()
表示文件的长度。如果File对象表示目录,则返回值未指定。
public long length();
注意
- 文件夹是没有大小概念的,不能获取文件夹的大小(length方法返回值不一定是0)
- 如果构造方法中给出的路径不存在,那么length方法返回0
代码如下:
public class FileGet {
public static void main(String[] args) {
File f = new File("d:/aaa/bbb.java");
System.out.println("文件绝对路径:"+f.getAbsolutePath());
System.out.println("文件构造路径:"+f.getPath());
System.out.println("文件名称:"+f.getName());
System.out.println("文件长度:"+f.length()+"字节");
File f2 = new File("d:/aaa");
System.out.println("目录绝对路径:"+f2.getAbsolutePath());
System.out.println("目录构造路径:"+f2.getPath());
System.out.println("目录名称:"+f2.getName());
System.out.println("目录长度:"+f2.length());
}
}
length(),表示文件的长度。如果File对象表示目录,则返回值未指定。
结果:
文件绝对路径:d:\aaa\bbb.java
文件构造路径:d:\aaa\bbb.java
文件名称:bbb.java
文件长度:636字节
目录绝对路径:d:\aaa
目录构造路径:d:\aaa
目录名称:aaa
目录长度:4096
判断功能的方法
- 此File表示的文件或目录是否实际存在(常用于判断构造方法中的路径是否存在)
public boolean exists();
- 此File表示的是否为目录
public boolean isDirectory();
- 此File表示的是否为文件
public boolean isFile();
代码如下:
public class FileIs {
public static void main(String[] args) {
File f = new File("d:\\aaa\\bbb.java");
File f2 = new File("d:\\aaa");
//不存在,就没有必要获取
if(f1.exists()){
System.out.println(f1.isDirectory());
System.out.println(f1.isFile());
}
if(f2.exists()){
System.out.println(f2.isDirectory());
System.out.println(f2.isFile());
}
}
}
创建删除的方法
创建文件、目录的路径和名称在构造方法中给出(构造方法的参数)
创建文件
- 当且仅当具有该名称的文件不存在时,创建一个新的空文件。
public boolean createNewFile();
注意
-
此方法只能创建文件,不能创建文件夹
-
创建文件的路径必须存在,否则会抛出异常
IOException
创建目录
public boolean mkdir()
:创建目录。public boolean mkdirs()
:创建多级目录,包括任何必需但不存在的父目录。
返回值:布尔值
- true:文件夹不存在,创建文件夹
- false:
- 文件夹存在,不会创建;
- 构造方法中给出的路径不存在也返回false ;
注意
- 此方法只能创建文件夹,不能创建文件
删除文件/目录
-
删除由此File表示的文件或目录。
如果此File表示目录,则目录必须为空才能删除。
public boolean delete();
代码如下:
public class FileCreateDelete {
public static void main(String[] args) throws IOException {
// 文件的创建
File f = new File("aaa.txt");
System.out.println("是否存在:"+f.exists()); // false
System.out.println("是否创建:"+f.createNewFile()); // true
System.out.println("是否存在:"+f.exists()); // true
// 注意!!!
File f3 = new File("E:\pic\\新建文件夹3");
boolean b3 = f3.createNewFile();
System.out.println(b3); // true 要看类型,不要被名字忽悠!
// 目录的创建
File f2= new File("newDir");
System.out.println("是否存在:"+f2.exists());// false
System.out.println("是否创建:"+f2.mkdir()); // true
System.out.println("是否存在:"+f2.exists());// true
// 注意!!!
File f2 = new File("E:\\pic\\aaa.txt");
boolean b2 = f1.mkdir();
System.out.println(b2); // true 创建的是目录,不要被名字忽悠!
// 创建多级目录
File f3= new File("newDira\\newDirb");
System.out.println(f3.mkdir());// false
File f4= new File("newDira\\newDirb");
System.out.println(f4.mkdirs());// true
// 文件的删除
System.out.println(f.delete());// true
// 目录的删除
System.out.println(f2.delete());// true
System.out.println(f4.delete());// false
}
}
4. 目录的遍历
第一种
- 获取该File目录中的所有【子文件或目录,包括隐藏文件和文件夹】
public String[] list();
原理
- 遍历构造方法中给出的目录,获取目录中所有文件/文件夹的名称
- 把获取到的多个名称存储到一个String类型的数组中
第二种
- 获取该File目录中的所有的【子文件或目录,包括隐藏文件和文件夹】
public File[] listFiles();
原理
- 遍历构造方法中给出的目录,获取目录中所有的文件/文件夹,把文件/文件夹封装为File对象。
- 把获取到的多个File对象存储到File数组中。
注意
list
方法和listFiles
方法遍历的是构造方法中给出的目录- 如果构造方法中给出的目录的路径不存在,会抛出空指针异常
- 如果构造方法中给出的路径不是一个目录,也会抛出空指针异常
代码:
public class FileFor {
public static void main(String[] args) {
File dir = new File("d:\\java_code");
//获取当前目录下的文件以及文件夹的名称。
String[] names = dir.list();
for(String name : names){
System.out.println(name);
}
//获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
File[] files = dir.listFiles();
for (File file : files) {
System.out.println(file);
}
}
}
调用
listFiles
方法的File
对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历。
结果:
[Ljava.lang.String;@50cbc42f
1.txt
111
43.jpg
aaa
我是一个文件夹.txt
我是一个隐藏文件.txt
我是一个隐藏文件夹
新建文件夹
新建文件夹3
=======================
[Ljava.io.File;@75412c2f
E:\pic\1.txt
E:\pic\111
E:\pic\43.jpg
E:\pic\aaa
E:\pic\我是一个文件夹.txt
E:\pic\我是一个隐藏文件.txt
E:\pic\我是一个隐藏文件夹
E:\pic\新建文件夹
E:\pic\新建文件夹3
5. 文件操作
文件搜索
搜索D:\aaa
目录中的.java
文件。
分析
- 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
- 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
代码实现
public class DiGuiDemo3 {
public static void main(String[] args) {
// 创建File对象
File dir = new File("D:\\aaa");
// 调用打印目录方法
printDir(dir);
}
public static void printDir(File dir) {
// 获取子文件和目录
File[] files = dir.listFiles();
// 循环打印
for (File file : files) {
if (file.isFile()) {
// 是文件,判断文件名并输出文件绝对路径
if (file.getName().endsWith(".java")) {
System.out.println("文件名:" + file.getAbsolutePath());
}
} else {
// 是目录,继续遍历,形成递归
printDir(file);
}
}
}
}
文件过滤器优化
在File类中有两个和ListFiles
重载的方法,方法的参数传递的就是过滤器。
第一种重载方法
File[] listFiles(FileFilter filter);
参数
java.io.FileFilter
是一个接口,用来过滤文件(File对象)。
其内部只有一个用来过滤文件的方法:
- 保留返回true,过滤返回false
boolean accept(File pathname);
原理
listFiles
方法进行了如下操作
- 遍历构造方法中给出的目录,获取目录中所有的文件/文件夹,把文件/文件夹封装为File对象。
- 调用参数传递过滤器的
accept
方法 - 把获取到的多个File对象,传递到accept方法的参数。
格式:
File dir = new File("E:\\a");
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
//过滤规则:pathname是文件夹,返回true
return pathname.isDirectory();
}
});
案例:遍历某路径下全部.txt
文件
分析;
- 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单。
accept
方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回false。保留规则:要么是.java文件。要么是目录,用于继续遍历。- 通过过滤器的作用
listFiles(FileFilter)
返回的数组元素中,子文件对象都是符合条件的,可直接打印。
代码实现:
public class DiGuiDemo4 {
public static void main(String[] args) {
File dir = new File("D:\\aaa");
printDir2(dir);
}
public static void printDir2(File dir) {
// 创建过滤器子类对象【匿名内部类方式】
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".java")||pathname.isDirectory();
}
});
// 【lambda的改写】
File[] files = dir.listFiles(f ->{
return f.getName().endsWith(".java") || f.isDirectory();
});
// 【简化lambda写法】
File[] files = dir.listFiles((pathname)->
pathname.isDirectory()
|| pathname.getName().toLowerCase().endsWith(".txt")
);
// 循环打印
for (File file : files) {
if (file.isFile()) {
System.out.println("文件名:" + file.getAbsolutePath());
} else {
// 【递归】
printDir2(file);
}
}
}
}
第二种重载方法
java.io.FilenameFilter
接口:实现此接口的类实例可用于过滤器文件名。
用于过滤文件名:
File[] listFiles(FilenameFilter filter);
其内部的抽象方法:
- 用来过滤文件的方法测试指定文件是否应该包含在某一文件列表中。
boolean accept(File dir, String name);
参数
-
File dir
:构造方法中传递的被遍历的目录 -
String name
:使用ListFiles方法遍历目录,获取的每一个文件/文件夹的名称
代码实现:
package cn.luis.demo03.Filter;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
public class Demo02Filter {
public static void main(String[] args) {
File file = new File("E:\\pic");
getAllFile(file);
}
/*
定义一个方法,参数传递File类型的目录
方法中对目录进行遍历
*/
// 匿名内部类方式
public static void getAllFile(File dir){ // 传递过滤器对象
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// File(dir,name):封装为一个File(文件)对象,组合成完整路径
return new File(dir,name).isDirectory() || name.toLowerCase().endsWith(".txt");
}
});
//分析:FilenameFilter是只有一个【方法】的接口,因此可以用lambda表达式简写。
//使用Lambda表达式优化匿名内部类(接口中只有一个抽象方法)
File[] files = dir.listFiles((File d, String name)-> {
return new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt");
});
// 简化lambda表达式
File[] files = dir.listFiles((d, name)->
new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt")
);
for (File f : files) {
//对遍历得到的File对象f进行判断,判断是否是文件夹
if(f.isDirectory()){
//f是一个文件夹,则继续遍历这个文件夹
//我们发现getAllFile方法就是传递文件夹,遍历文件夹的方法
//所以直接调用getAllFile方法即可:递归(自己调用自己)
getAllFile(f); // 递归
}else{
//f是一个文件,直接打印即可
System.out.println(f);
}
}
}
}
结果:
E:\pic\1.txt
E:\pic\我是一个隐藏文件.txt