【Java I/O 流】4 - 1 File 类
§4-1 File
类
4-1.1 File
类概述
File
类位于 java.io
包下,用于抽象表示一个文件或一个目录路径,该路径可以是存在的,也可以是不存在的。
用户界面和操作系统使用系统独立的路径名称字符串来命名文件和目录。该类表示一个抽象、系统独立的等级路径。
路径有相对路径与绝对路径之分。相对路径不带盘符,相对于当前项目的路径,如 a.txt
, abc\\a.txt
;绝对路径带盘符,如 C:\\a.text
。
构造方法:
构造方法 | 描述 |
---|---|
File(String pathname) |
根据字符串指定的路径创建一个文件实例 |
File(File parent, String child) |
根据父路径示例和子路径创建一个文件实例 |
File(String parent, String child) |
根据根据父路径和子路径字符串创建一个文件实例 |
4-1.2 File
的成员方法
对于一个文件,其最常见的操作就是增删改查,File
类中提供了这些方法,以及一下其他的判断方法来完成这些操作。
用于判断、获取的成员方法:
方法 | 描述 |
---|---|
boolean exists() |
测试该路径是否存在 |
boolean isAbsolute() |
测试该路径是否为绝对路径 |
boolean isDirectory() |
测试路径是否为一个目录 |
boolean isFile() |
测试路径是否为一个文件 |
boolean isHidden() |
测试文件是否隐藏 |
File getAbsoluteFile() |
返回绝对路径形式的 File 实例 |
String getAbsolutePath() |
返回绝对路径字符串 |
String getName() |
获取文件或目录的名称(带后缀) |
String getParent() |
获取父路径字符串 |
File getParentFile() |
获取父路径的 File 实例 |
String getPath() |
获取路径字符串 |
long lastModified() |
获取文件的最后修改时间 |
long length() |
返回文件的长度(文件大小,字节) |
注意:
- 当路径不存在时,
isAbsolute
,isDirectory
,isFile
,isHidden
全部为false
; length
方法无法正确获取目录大小,若想要获取目录大小,应当遍历目录中所有文件,将结果累加;getName
方法可以用于获取文件或目录的名字,获取文件名时会同时获得其扩展名;lastModified
返回的是毫秒值,可以使用时间类毫秒值格式化为指定格式的日期;
用于创建、删除的成员方法:
方法 | 描述 |
---|---|
boolean createNewFile() |
创建一个新的空文件 |
boolean delete() |
删除文件或空目录 |
boolean mkdir() |
创建单级目录 |
boolean mkdirs() |
创建多级目录 |
注意:
- 所有方法当且仅当成功执行时返回
true
; createNewFile
当且仅当文件不存在时创建一个空文件,若找不到路径,则抛出异常IOException
,需要在调用处处理该异常;mkdir
不能创建多级目录,mkdirs
既能够创建单级目录,也能创建多级目录,建议使用后者;delete
仅能删除空目录,若目录不为空,无法删除,且注意,删除文件/目录时,被删除对象并不会进入回收站;
用于获取、遍历的方法:
方法 | 描述 |
---|---|
String[] list() |
返回含有该目录下所有文件和子目录名字的字符串数组 |
String[] list(FilenameFilter filter) |
使用文件名过滤器,返回含有该目录下所有文件和子目录名字的字符串数组 |
File[] listFiles() |
返回含有该目录下所有文件和子目录的 File 数组 |
File[] listFiles(FileFilter filter) |
使用文件过滤器,返回含有该目录下所有文件和子目录的 File 数组 |
File[] listFiles(FilenameFilter filter) |
使用文件名过滤器,返回含有该目录下所有文件和子目录的 File 数组 |
static File[] listRoots() |
返回可用的文件系统根(盘符) |
注意:
-
FileFilter
和FilenameFilter
是位于java.io
下的函数式接口,二者都含有一个抽象方法accept
,返回值类型为boolean
,若返回true
,则指定的路径应当保留,否则舍弃; -
FilenameFilter
中的accept
具有两个参数:File dir, String name
,分别表示父级路径和子级路径;若遍历的路径为
D:\\folder
,对于其中一个文件text.txt
,上述的两个形参分别指代D:\\folder
,text.txt
(注意类型); -
FileFilter
中的accept
只有一个形参File pathname
,表示目录下的每个文件/子目录,并不会像前者将其拆分为父级目录和子级路径;若遍历的路径为
D:\\folder
,对于其中一个文件text.txt
,则该方法的形参指代D:\\folder\\text.txt
;
listFiles
实现细节:
- 当调用者所表示的路径不存在时,返回
null
; - 当调用者所表示的路径为文件时,返回
null
; - 当调用者所表示的路径为一个空目录时,返回一个长度为 0 的数组;
- 当调用者所表示的路径为一个非空目录时,返回其中所有的内容(文件、子目录,含隐藏文件);
- 当调用者所表示的路径是一个需要访问权限的目录时,返回
null
;
4-1.3 案例演示
需求一:在当前路径下的 aaa
文件夹中,新建一个 a.txt
文件。
File f1 = new File("JavaSE\\aaa"); //相对路径
File f2 = new File(f1, "a.txt"); //文件
f1.mkdirs(); //考虑到目录可能不存在
try {
f2.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("==============");
需求二:定义一个方法,寻找某一目录及其所有子目录中,含有多少个 .mp4
文件。
//只接受目录
public static int deepFindMP4(String pathname) {
Objects.requireNonNull(pathname); //参数非空
File dir = new File(pathname);
File[] files = dir.listFiles();
int res = 0;
//非空:不存在、为文件、无权限
if (files != null) {
for (File file : files) {
if (file.isFile() && file.getName().endsWith(".mp4"))
res++;
else if (file.isDirectory())
res = res + deepFindMP4(file.getPath()); //递归调用计算子级目录文件数量,并累加
}
}
return res;
}
需求三:删除一个非空文件夹。
public static boolean delDirs(String pathname) {
Objects.requireNonNull(pathname); //参数非空
File dir = new File(pathname);
File[] files = dir.listFiles(); //获取待删除目录的子文件
//遍历子级目录,删除子级目录(非 null)
if (files != null) {
for (File file : files) {
//判断是不是文件夹
if (file.isFile())
file.delete(); //删除子级目录/文件
else
//递归删除子目录
delDirs(file.getAbsolutePath());
}
}
//不存在、是文件、空目录,直接删:删自己
return dir.delete();
}
需求四:统计一个目录的大小。
public static long countSize(File dir) {
Objects.requireNonNull(dir); //参数非空
long size = 0;
if (dir.isFile())
size = dir.length(); //若为文件,直接返回文件大小
else {
//若为目录,遍历
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
size += countSize(file); //递归调用计算子目录大小,并累加
}
}
}
return size;
}
需求五:统计一个目录不同类型文件的数目。
//仅接受目录
public static void countTypes(File dir, HashMap<String, Integer> stats) {
Objects.requireNonNull(dir);
Objects.requireNonNull(stats);
File[] files = dir.listFiles();
//为空:不存在、为文件、无权限
if (files != null) {
for (File file : files) {
//递归访问子目录
if (file.isDirectory())
countTypes(file, stats);
else {
//对于目录中的文件,获取扩展名
String[] partitions = file.getName().split("\\.");
String extension = "文件"; //考虑到无后缀名的文件
if (partitions.length != 1) {
extension = partitions[partitions.length - 1].toLowerCase();
//后缀名大小写不敏感,全部转换为小写
}
stats.merge(extension, 1, Integer::sum);
}
}
}
}