7.1 File类的基本操作(一)

系列 -
目录
本节摘要
这一节我们将学习Java中的文件操作基础知识。通过动手实验,你将掌握如何使用File类进行文件和目录的创建、删除、遍历等基本操作。这些知识是后续学习文件读写的重要基础。
任务一:File常用操作
1、文件的创建和删除
在Java中,File类不仅可以表示文件,也可以表示目录(文件夹)。让我们从简单的文件创庺开始:
重要概念
- File对象只是一个路径的抽象表示,创建File对象并不会真正创建文件
- 需要调用
createNewFile()
方法才能真正创建文件
import java.io.File;
public class Example01 {
public static void main(String[] args) {
/**
* Step 1 创建普通文件
*/
// 创建File对象,指定文件路径
File file1 = new File("out/chapter7/file1.txt");
if (file1.exists()) {
// 如果文件存在就删除
System.out.println("文件存在");
file1.delete();
System.out.println("文件已删除");
} else {
// 如果文件不存在就创建
System.out.println("文件不存在");
try {
file1.createNewFile();
System.out.println("文件已创建");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("\n");
}
}
可能的问题
运行上面的代码时,如果
out/chapter7/
这个目录不存在,程序会抛出异常。因为创建文件之前,必须先创建父目录。下面的代码展示了如何正确处理这个问题:
创建目录的方法
mkdirs()
- 创建多级目录,如a/b/c
一次性创建所有不存在的目录mkdir()
- 只能创建单级目录,父目录必须先存在- 建议使用
mkdirs()
,更安全可靠
2、遍历目录内容
基本概念
在操作系统中,目录(文件夹)也是一种特殊的文件,只不过它的内容是其他文件和子目录的名单。
Java提供了多种遍历目录的方式,让我们从简单的开始:
方法一:简单遍历
这种方法只能获取文件名,不能区分文件和目录:
import java.io.File;
public class Example03 {
public static void main(String[] args) {
File file = new File("src");
if (file.isDirectory()) {
System.out.println("是目录");
String[] names = file.list();
for (String name : names) {
System.out.println(name);
}
}
}
}
方法二:带过滤器的遍历
有时候我们只关心特定类型的文件,可以使用过滤器:
import java.io.File;
import java.io.FilenameFilter;
public class Example04 {
public static void main(String[] args) {
// 创建 File 对象
File file = new File("src");
// 创建过滤器对象
FilenameFilter filter = new FilenameFilter() {
// 这个方法决定哪些文件会被包含在结果中
@Override
public boolean accept(File currFile, String name) {
// 只要.java文件
if (name.endsWith(".java")) {
return true; // 返回true表示接受这个文件
} else {
return false; // 返回false表示过滤掉这个文件
}
}
};
if (file.exists() && file.isDirectory()) {
String[] names = file.list(filter);
for (String name : names) {
System.out.println(name);
}
}
}
}
3、深度遍历目录(递归遍历)
前面的例子都只能遍历当前目录下的文件,但如果目录下还有子目录,就需要用到递归遍历。
list() vs listFiles()
list()
- 返回字符串数组,只有文件名listFiles()
- 返回File对象数组,可以进一步操作每个文件
import java.io.File;
public class Example05 {
public static void main(String[] args) {
File file = new File("src");
showFiles(file);
}
/**
* 递归显示指定目录下的所有文件(包括子目录中的文件)
* @param dir 要遍历的目录
*/
public static void showFiles(File dir) {
// 获取当前目录下所有文件和子目录的数组
File[] fileArray = dir.listFiles();
if (fileArray == null) return; // 防止空指针异常
for (File file : fileArray) {
if (file.isDirectory()) {
// 如果是目录,就递归调用自己来遍历子目录
showFiles(file);
}
// 打印文件的绝对路径
System.out.println(file.getAbsolutePath());
}
}
}
4、删除文件和目录
File类的delete()
方法可以删除文件或目录,但有一些限制。让我们先看一个简单的例子:
准备测试数据
在电脑的D盘中创建一个名为
hello
的文件夹,并在里面放一个文本文件。然后试试用下面的代码删除。import java.io.File;
public class Example06 {
public static void main(String[] args) {
File file = new File("d:/hello");
if (file.exists()) {
if (file.delete()) {
System.out.println("删除成功!");
} else {
System.out.println("删除失败!");
}
}
}
}
为什么删除失败?
delete()
方法有一个重要限制:只能删除空目录或文件。如果目录下还有其他文件或子目录,删除就会失败。要删除非空目录,必须先删除里面的所有内容,再删除目录本身。这需要用到递归:
import java.io.File;
public class Example07 {
public static void main(String[] args) {
File dir = new File("d:/hello");
deleteFiles(dir);
}
/**
* 递归删除整个目录(包括其中的所有文件和子目录)
* @param dir 要删除的目录
*/
public static void deleteFiles(File dir) {
if (dir.exists()) {
File[] files = dir.listFiles();
if (files != null) { // 防止空指针异常
// 先删除目录下的所有内容
for (File file : files) {
if (file.isDirectory()) {
// 如果是子目录,递归删除
deleteFiles(file);
} else {
// 如枟是文件,直接删除
file.delete();
}
}
}
// 最后删除空目录本身
dir.delete();
}
}
}
删除操作风险
注意:Java的
delete()
方法是永久删除,不会放入回收站!文件一旦删除就无法恢复,所以在使用时要格外小心。知识补充:匿名内部类
在前面的过滤器代码中,我们用到了匿名内部类。这是Java中一个很实用的特性:
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File currFile, String name) {
// 方法实现
}
};
匿名内部类的原理
这种写法相当于同时做了三件事:
- 定义了一个实现FilenameFilter接口的类(没有名字,所以叫匿名类)
- 创建了这个类的对象
- 把对象赋值给filter变量
等价的常规写法:
// 先定义一个实现类
class MyFilter implements FilenameFilter {
@Override
public boolean accept(File currFile, String name) {
if (currFile.isFile() && name.endsWith(".java")) {
return true;
} else {
return false;
}
}
}
// 然后创建对象
FilenameFilter filter = new MyFilter();
练习作业
作业1:搜索指定类型文件
编写一个程序,实现以下功能:
- 搜索指定目录下的所有以
.txt
结尾的文件(只搜索当前目录,不包括子目录) - 显示文件名和文件大小(以KB为单位)
- 统计找到的文件总数
参考代码框架:
import java.io.File;
import java.io.FilenameFilter;
public class FileSearcher {
public static void main(String[] args) {
// 请将此处替换为你的目录路径
File directory = new File("D:\\test");
// 检查目录是否存在,若不存在需要给出提示,并退出程序
// 待实现:创建文件过滤器,只接受.txt文件
FilenameFilter filter = null; // 在此处修改,实现文件过滤器
// 待实现:遍历目录,打印文件信息
// 待实现:统计文件总数
}
}
要求:
- 使用匿名内部类实现FilenameFilter
- 文件大小要求显示为KB为单位
- 要处理目录不存在的情况
预期输出格式:
文件名:test1.txt,大小:1.5 KB
文件名:test2.txt,大小:2.3 KB
文件名:note.txt,大小:0.5 KB
共找到 3 个txt文件
作业2:深度搜索并删除文件
编写一个程序,实现以下功能:
- 递归搜索指定目录下的所有以
.java
结尾的文件(包括子目录中的) - 显示文件名和文件大小(以KB为单位)
- 删除找到的文件
- 统计删除的文件总数
要求:
- 使用匿名内部类实现FilenameFilter
- 文件大小要求显示为KB为单位
- 要处理目录不存在的情况
预期输出格式:
文件名:test1.java,大小:1.5 KB
文件名:test2.java,大小:2.3 KB
文件名:note.java,大小:0.5 KB
已删除 test1.java
已删除 test2.java
已删除 note.java
共删除 3 个java文件