零、本讲学习目标
1、熟悉File类的常用方法
2、掌握File类遍历目录文件的使用
3、掌握File类删除文件及目录的使用
一、File类概述
通过I/O流可以对文件的内容进行读写操作,但对文件本身进行的一些常规操作是无法通过I/O流来实现的,例如创建一个文件、删除或者重命名某个文件、判断硬盘上某文件是否存在等。针对文件的这类操作,JDK中提供了一个File类,该类封装了一个路径,并提供了一系列的方法用于操作该路径所指向的文件,本讲我们围绕着File类展开学习。
1、File的类继承图
从上图可以看到,File类是Object类的直接子类,实现了两个接口:序列化接口(Serializable)和可比较接口(Comparable)。
2、File类的结构
从上图可以看到,File提供了六种重载的构造方法,还提供了一系列获取文件属性的方法。
二、File类常用方法
1、File类常用构造方法
方法声明 | 功能描述 |
---|---|
File(String pathname) | 通过指定的一个字符串类型的文件路径来创建一个新的File对象 |
File(String parent, String child) | 根据指定的一个字符串类型的父路径和一个字符串类型的子路径(包括文件名称)创建一个File对象 |
File(File parent, String child) | 根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象 |
2、File类常用普通方法
方法声明 | 功能描述 |
---|---|
boolean exists() | 判断File对象对应的文件或目录是否存在,若存在则返回ture,否则返回false |
boolean delete() | 删除File对象对应的文件或目录,若成功删除则返回true,否则返回false |
boolean createNewFile() | 当File对象对应的文件不存在时,该方法将新建一个此File对象所指定的新文件,若创建成功则返回true,否则返回false |
String getName() | 返回File对象表示的文件或文件夹的名称 |
String getPath() | 返回File对象对应的路径 |
String getAbsolutePath() | 返回File对象对应的绝对路径(在Unix/Linux等系统上,如果路径是以正斜线/开始,则这个路径是绝对路径;在Windows等系统上,如果路径是从盘符开始,则这个路径是绝对路径) |
String getParent() | 返回File对象对应目录的父目录(即返回的目录不包含最后一级子目录) |
boolean canRead() | 判断File对象对应的文件或目录是否可读,若可读则返回true,反之返回false |
boolean canWrite() | 判断File对象对应的文件或目录是否可写,若可写则返回true,反之返回false |
boolean isFile() | 判断File对象对应的是否是文件(不是目录),若是文件则返回true,反之返回false |
boolean isFile() | 判断File对象对应的是否是文件(不是目录),若是文件则返回true,反之返回false |
boolean isDirectory() | 判断File对象对应的是否是目录(不是文件),若是目录则返回true,反之返回false |
boolean isAbsolute() | 判断File对象对应的文件或目录是否是绝对路径 |
long lastModified() | 返回1970年1月1日0时0分0秒到文件最后修改时间的毫秒值 |
long length() | 返回文件内容的长度 |
String[] list() | 列出指定目录的全部内容,只是列出名称 |
String[] list(FilenameFilter filter) | 接收一个FilenameFilter参数,通过该参数可以只列出符合条件的文件 |
File[] listFiles() | 返回一个包含了File对象所有子文件和子目录的File数组 |
三、利用File类实现文件操作
(一)创建目录
1、创建方法
调用File对象的mkdir()
方法就可以创建目录,返回true
,表明创建目录成功,否则创建失败。(mk: make;dir: directory)
2、案例演示
- 创建Example2601
package net.hw.lesson26;
import java.io.File;
/**
* 功能:创建目录
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2601 {
public static void main(String[] args) {
// 创建File对象,指向一个目录,仅仅是一个逻辑概念
File dir = new File("d:/park01");
// 调用File对象的创建目录方法,将逻辑概念转换成物理实在
boolean isDirMade = dir.mkdir();
// 判断目录是否创建成功
if (isDirMade) {
// getPath()方法返回File对象对应的路径
System.out.println("目录[" + dir.getPath() + "]创建成功!");
} else {
System.out.println("目录[" + dir.getPath() + "]创建失败!");
}
}
}
- 运行程序,查看结果
- 验证是否在指定位置创建了目录
- 代码说明
–File dir = new File("d:/park01");
与File dir = new File("d:\\park01");
是一样的效果,因为“\”是转义字符的打头字符,所以写反斜杠目录分隔符就需要两个反斜杠“\\”。
– 如果创建File对象的语句变成File dir = new File("park01");
传入的参数只有目录名而没有盘符或路径,那么调用dir的mkdir()方法后,将在项目根目录创建一个park01目录,同学们不妨验证一下。 - 再一次运行程序,查看结果
- 说明:失败的原因是因为目录已经存在,我们可以在创建目录时判断目录是否存在,然后给用户相应的提示。
- 修改Example2601,创建目录时判断目录是否存在,不存在时再调用创建目录方法
package net.hw.lesson26;
import java.io.File;
/**
* 功能:创建目录
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2601 {
public static void main(String[] args) {
// 创建File对象,指向一个目录,仅仅是一个逻辑概念
File dir = new File("d:/park01");
// 判断目录是否存在
if (!dir.exists()) {
// 调用File对象的创建目录方法,将逻辑概念转换成物理实在
boolean isDirMade = dir.mkdir();
// 判断目录是否创建成功
if (isDirMade) {
// getPath()方法返回File对象对应的路径
System.out.println("目录[" + dir.getPath() + "]创建成功!");
} else {
System.out.println("目录[" + dir.getPath() + "]创建失败!");
}
} else {
System.out.println("目录[" + dir.getPath() + "]已经存在!");
}
}
}
- 运行程序,查看结果
- 说明:目录必须一层一层地创建,比如创建
d:\park01
,然后再创建d:\park01\hw
就没有问题,否则就会创建失败。 - 在Windows窗口里删除
d:\park01
目录,程序中直接创建d:\park01\hw
- 先创建
d:\park01
- 再创建
d:\park01\hw
- 结论:利用File对象创建目录,必须一级目录一级目录地创建,就像修建房屋,要一层楼一层楼地往上修,一楼都没有修,直接修二楼,肯定是要不得的。
(二)创建文件
1、创建方法
调用File对象的creatNewFile()
方法就可以创建文件,返回true
,表明创建文件成功,否则创建失败,而且有可能抛出无效文件路径的I/O异常。
2、案例演示
- 创建Example2602
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
/**
* 功能:创建文件
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2602 {
public static void main(String[] args) {
// 创建File对象,指向一个文件,仅仅是一个逻辑概念
File file = new File("d:/park01", "love.txt");
try {
// 调用File对象的创建文件方法,将逻辑概念转换成物理实在
file.createNewFile();
// 提示用户文件创建成功
System.out.println("文件[" + file.getAbsolutePath() + "]创建成功!");
} catch (IOException e) {
// 提示用户文件创建失败
System.out.println("文件[" + file.getAbsolutePath() + "]创建失败!");
}
}
}
- 代码说明:创建指向文件的File对象既可以利用构造方法
public File(String parent, String child)
,此时parent
参数是一个路径字符串,也可以利用构造方法public File(File parent, String child)
,在案例Example2603里我们会用第二种构造方法来创建文件对象。 - 运行程序,查看结果
- 修改一下创建File对象时传入的第一个参数,改成一个不存在的目录,在异常捕获代码块里添加一条输出异常信息的语句,然后执行程序,查看效果
- 修改程序,在创建文件时判断文件是否存在
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
/**
* 功能:创建文件
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2602 {
public static void main(String[] args) {
// 创建File对象,指向一个文件,仅仅是一个逻辑概念
File file = new File("d:/park01", "love.txt");
// 判断文件是否存在
if (!file.exists()) {
try {
// 调用File对象的创建文件方法,将逻辑概念转换成物理实在
file.createNewFile();
// 提示用户文件创建成功
System.out.println("文件[" + file.getAbsolutePath() + "]创建成功!");
} catch (IOException e) {
// 提示用户文件创建失败
System.out.println("文件[" + file.getAbsolutePath() + "]创建失败!");
System.err.println("异常信息:" + e.getMessage());
}
} else {
// 提示用户文件已经存在
System.out.println("文件[" + file.getAbsolutePath() + "]已经存在!");
}
}
}
- 运行程序,查看效果
(三)获取目录或文件的属性
1、获取方法
2、案例演示
- 创建Example2603
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* 功能:获取目录与文件的属性
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2603 {
public static void main(String[] args) throws IOException {
// 创建目录对象(注意目录是已经存在的)
File dir = new File("d:/park01");
// 创建文件对象(注意文件是已经存在的)
File file = new File(dir, "love.txt");
// 创建简单日期格式对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
// 获取目录相关属性
System.out.println("目录路径:" + dir.getPath());
System.out.println("目录父目录:" + dir.getParent());
System.out.println("目录绝对路径:" + dir.getAbsolutePath());
System.out.println("目录标准路径:" + dir.getCanonicalPath());
System.out.println("目录名:" + dir.getName());
System.out.println("目录长度:" + dir.length());
System.out.println("目录最后修改时间:" + sdf.format(dir.lastModified()));
System.out.println();
// 获取文件的相关属性
System.out.println("文件路径:" + file.getPath());
System.out.println("文件父目录:" + file.getParent());
System.out.println("文件绝对路径:" + file.getAbsolutePath());
System.out.println("文件标准路径:" + file.getCanonicalPath());
System.out.println("文件名:" + file.getName());
System.out.println("文件长度:" + file.length());
System.out.println("文件最后修改时间:" + sdf.format(file.lastModified()));
}
}
- 运行程序,查看结果
- 修改文件love.txt,添加一点内容
- 再次运行程序,查看结果
(四)遍历目录下的文件
1、获取方法
- 一个是重载的list()返回的是目录名或文件名数组(可以接收文件名过滤作为参数)
- 一个是重载的listFiles()返回的是File对象数组(可以接收文件名过滤器或文件过滤器作为参数)
2、案例演示:显示指定目录下所有子目录与文件的名称
package net.hw.lesson26;
import java.io.File;
/**
* 功能:显示指定目录下所有子目录与文件的名称
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2604 {
public static void main(String[] args) {
// 创建File对象,指向目录(c:\windows)
File dir = new File("c:/windows");
// 判断是否是目录
if (dir.isDirectory()) {
// 获取指定目录下全部文件或目录名
String[] filenames = dir.list();
// 遍历文件名数组
for (String filename : filenames) {
System.out.println(dir.getPath() + "\\" + filename);
}
} else {
System.err.println("[" + dir.getPath() + "]不是目录!");
}
}
}
- 运行程序,查看结果
- 除了用增强for循环来遍历filenames数组,还可以使用JDK8提供的stream的forEach方法来遍历,当然要利用Lambda表达式
Arrays.stream(filenames).forEach(filename -> System.out.println(dir.getPath() + "\\" + filename));
- 还可以利用Arrays类的asList()方法将数组转换成数组列表,再利用forEach()和Lambda表达式来遍历整个数组的全部元素
Arrays.asList(filenames).forEach(filename -> System.out.println(dir.getPath() + "\\" + filename));
- 如果将程序中的目录名
c:/windows
改成一个文件名c:/windows/win.ini
,运行程序,结果会怎样呢?我们不妨来试一试。
子目录名与文件名是混在一起的,那么怎样才能将目录和文件分开显示呢?
3、案例演示:分开显示指定目录下的子目录与文件
-
方法:要利用File对象的listFiles()方法来获取指定目录下的File对象数组,然后利用File对象的isDirectory()方法和isFile()方法来区分获取的File对象是目录还是文件。
-
创建Example2605
package net.hw.lesson26;
import java.io.File;
/**
* 功能:分开显示指定目录下的子目录与文件
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2605 {
public static void main(String[] args) {
// 创建File对象,指向一个目录(c:\windows)
File dir = new File("c:/windows");
// 获取指定目录下的子目录与文件对象数组
File[] files = dir.listFiles();
// 显示指定目录下的子目录
System.out.println(dir.getPath() + "下的子目录:");
// 遍历files数组,筛选出子目录
for (File file: files) {
if (file.isDirectory()) {
System.out.println(file.getPath());
}
}
System.out.println("=======================");
// 显示指定目录下的文件
System.out.println(dir.getPath() + "下的文件:");
// 遍历files数组,筛选出文件
for (File file: files) {
if (file.isFile()) {
System.out.println(file.getPath());
}
}
}
}
- 运行程序,查看结果
如何查看某个目录下指定类型的文件?比如我们只想查看c:\windows
目录下的文本文件。
4、案例演示:显示指定目录下某种类型的文件
- 方法:在File对象的list()或listFiles()里传入文件名过滤器对象或者利用Lambda表达式来实现文件类型的过滤
- 创建Example2606
package net.hw.lesson26;
import java.io.File;
import java.io.FilenameFilter;
/**
* 功能:显示指定目录下某种类型的文件
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2606 {
public static void main(String[] args) {
// 创建File对象,指向目录(c:\windows)
File dir = new File("c:/windows");
// 获取指定目录下全部可执行文件名
String[] filenames = dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".exe");
}
});
System.out.println(dir.getPath() + "下的可执行文件:");
// 遍历文件名数组
for (String filename: filenames) {
System.out.println(filename);
}
}
}
- 运行程序,查看结果
- 修改程序,采用Lambda表达式来过滤和遍历
package net.hw.lesson26;
import java.io.File;
import java.util.Arrays;
/**
* 功能:显示指定目录下某种类型的文件
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2606 {
public static void main(String[] args) {
// 创建File对象,指向目录(c:\windows)
File dir = new File("c:/windows");
// 获取指定目录下全部可执行文件名
String[] filenames = dir.list((parent, filename) -> filename.endsWith(".exe"));
System.out.println(dir.getPath() + "下的可执行文件:");
// 文件名数组转换成数组列表后进行遍历
Arrays.asList(filenames).forEach(filename -> System.out.println(filename));
}
}
- 运行程序,查看结果
5、案例演示:采用递归算法生成指定目录下某种类型文件的列表
- 注意:目录下还有目录,一层又一层的目录,都要遍历到,必须采用递归才能搞定。
- 创建Example2607
package net.hw.lesson26;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 功能:生成指定目录下某种类型文件的列表
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2607 {
/**
*
* @param dir 目录
* @param suffix 后缀
* @param typeFileList 类型文件列表
*/
public static void makeTypeFileList(File dir, String suffix, List<String> typeFileList) {
// 获取指定目录的File数组
File[] files = dir.listFiles();
// 遍历File数组
for(int i = 0; i < files.length; i++) {
// 判断File数组的元素是不是文件
if (files[i].isFile()) {
// 过滤文件类型
if (files[i].getPath().endsWith(suffix)) {
// 将文件添加到文件列表里
typeFileList.add(files[i].getPath());
}
} else {
// 判断目录是否为空
if (files[i].list() != null) {
// 递归调用
makeTypeFileList(files[i], suffix, typeFileList);
}
}
}
}
public static void main(String[] args) {
// 创建目录对象
File dir = new File("e:/");
// 创建类型文件列表
List<String> typeFileList = new ArrayList<>();
// 调用生成类型文件列表方法
makeTypeFileList(dir, ".mp3", typeFileList);
// 遍历类型文件列表
typeFileList.forEach(file -> System.out.println(file));
}
}
- 运行程序,查看结果(查看e盘所有mp3文件,比较耗时,要有点耐心)
6、课堂练习:遍历某个目录下的全部文件
比如,遍历“C:\Windows\apppatch”目录的全部文件:
(五)删除目录和文件
1、删除方法
调用File对象的delete()方法删除文件或目录。
2、案例演示:通过递归删除指定目录下的文件与文件夹
删除我们在前面创建的d:\park01
,因为它非空,必须采用递归法来删除它里面的全部东东。把它删成空目录之后,才能最终将它删除掉。
- 创建Example2608
package net.hw.lesson26;
import java.io.File;
/**
* 功能:通过递归删除指定目录下的文件与文件夹
* 作者:华卫
* 日期:2020年05月26日
*/
public class Example2608 {
public static void main(String[] args) {
// 创建目录对象
File dir = new File("d:/park01");
// 调用删除目录方法
deleteDir(dir);
// 提示用户删除成功
System.out.println("目录[" + dir.getPath() + "]删除成功!");
}
/**
* 删除指定目录下的全部东东
*
* @param dir
*/
public static void deleteDir(File dir) {
// 获取指定目录下的全部File对象
File[] files = dir.listFiles();
// 遍历File对象数组
for (File file : files) {
// 如果是目录,则递归调用删除方法
if (file.isDirectory()) {
deleteDir(file);
} else {
file.delete();
}
}
// 删除指定目录
dir.delete();
}
}
- 运行程序,查看结果