1. 创建文件
在程序中创建文件是很常见的需求:用于日志、临时数据、报表导出、数据导入、保存设置等。在 Java 中,正如你可能已经猜到的,最好使用现代 API——java.nio.file。
核心工具:Files.createFile(Path)
该方法按给定路径创建新文件。若文件已存在,将抛出异常。
示例:在当前目录创建一个文本文件
import java.nio.file.*;
public class CreateFileExample {
public static void main(String[] args) {
Path path = Path.of("hello.txt");
try {
Files.createFile(path);
System.out.println("文件已创建:" + path.toAbsolutePath());
} catch (FileAlreadyExistsException e) {
System.out.println("文件已存在:" + path);
} catch (Exception e) {
System.out.println("创建文件时出错:" + e.getMessage());
}
}
}
请注意:
Files.createFile 会在文件已存在时抛出 FileAlreadyExistsException。因此常在创建前检查文件是否存在。
检查文件是否存在
Path path = Path.of("hello.txt");
if (!Files.exists(path)) {
Files.createFile(path);
}
提示:
检查是否存在并不能防止并发竞态,但对大多数用户场景来说已经足够实用。
简述:创建文件时会发生什么?
- 如果文件不存在且路径有效——将创建一个新的空文件。
- 如果文件已存在——会抛出异常。
- 如果路径无效、无权限或目录不存在——会抛出其他异常(如 IOException、NoSuchFileException 等)。
2. 创建目录
Files.createDirectory 与 Files.createDirectories 的区别
- Files.createDirectory(Path) —— 仅创建一个目录。若父目录不存在——会报错。
- Files.createDirectories(Path) —— 会创建缺失的整条目录链(就像一个魔法师在你脚下现搭楼梯)。
示例:创建单个目录
Path dir = Path.of("data");
try {
Files.createDirectory(dir);
System.out.println("目录已创建:" + dir.toAbsolutePath());
} catch (FileAlreadyExistsException e) {
System.out.println("目录已存在:" + dir);
} catch (Exception e) {
System.out.println("创建目录时出错:" + e.getMessage());
}
示例:创建嵌套目录结构
Path nested = Path.of("data/reports/2024");
try {
Files.createDirectories(nested);
System.out.println("目录结构已创建:" + nested.toAbsolutePath());
} catch (Exception e) {
System.out.println("创建结构时出错:" + e.getMessage());
}
请注意:如果某些目录已经存在,createDirectories 并不介意——它只会创建缺失的部分。若对嵌套目录使用 createDirectory 而父目录尚不存在——会报错。
表格:创建目录方法对比
| 方法 | 仅创建单个目录 | 可创建嵌套目录 | 部分已存在时不报错 |
|---|---|---|---|
|
✔ | ✗ | ✗ |
|
✔ | ✔ | ✔ |
3. 删除文件
删除文件就像倒垃圾:关键是别把需要的东西扔了!在 Java 中主要有两种方法:
- Files.delete(Path) —— 删除文件或空目录。若目标不存在——会抛出异常。
- Files.deleteIfExists(Path) —— 删除文件,但如果目标不存在——静默无操作。
示例:删除临时文件
Path tempFile = Path.of("temp.txt");
try {
Files.delete(tempFile);
System.out.println("文件已删除:" + tempFile);
} catch (NoSuchFileException e) {
System.out.println("未找到文件:" + tempFile);
} catch (DirectoryNotEmptyException e) {
System.out.println("目录非空:" + tempFile);
} catch (Exception e) {
System.out.println("删除时出错:" + e.getMessage());
}
更安全的做法
boolean deleted = Files.deleteIfExists(tempFile);
if (deleted) {
System.out.println("文件已被删除。");
} else {
System.out.println("未找到文件——无需删除。");
}
重要!
- 如果文件正被其他程序打开,可能会抛出异常(例如在 Windows 上)。
- 若尝试删除非空目录,将抛出 DirectoryNotEmptyException。
4. 删除目录
在 Java 中删除目录与删除文件相似。但有个细节:标准方法只能删除 空 目录。
示例:删除空目录
Path emptyDir = Path.of("empty_folder");
try {
Files.delete(emptyDir);
System.out.println("目录已删除:" + emptyDir);
} catch (DirectoryNotEmptyException e) {
System.out.println("目录非空:" + emptyDir);
} catch (NoSuchFileException e) {
System.out.println("未找到目录:" + emptyDir);
} catch (Exception e) {
System.out.println("删除目录时出错:" + e.getMessage());
}
非空目录怎么办?
要删除非空目录,需要递归删除其内所有文件和子目录。这值得单独一讲(也是一次小冒险),但如果你已经迫不及待,请看下面的代码,理解并尝试复现:
import java.nio.file.*;
import java.io.IOException;
public class DeleteDirectoryRecursively {
public static void deleteRecursively(Path path) throws IOException {
if (Files.isDirectory(path)) {
try (var entries = Files.list(path)) {
for (Path entry : entries.toList()) {
deleteRecursively(entry);
}
}
}
Files.delete(path);
}
}
注意:
这段代码会删除目录中的一切!请谨慎使用。
5. 实践建议
删除前先检查是否存在
if (Files.exists(path)) {
Files.delete(path);
} else {
System.out.println("文件/目录不存在。");
}
但如果使用 deleteIfExists,就没必要这样做。
处理异常
处理文件时经常会遇到各种意外。为此 Java 会抛出不同类型的异常:
- NoSuchFileException —— 文件或目录未找到。例如你尝试打开已删除的对象。
- DirectoryNotEmptyException —— 你想删除目录,但里面还有内容。
- IOException —— 通用告警:出了点问题。可能原因很多——无访问权限、文件被其他程序占用、路径不正确。
可视化示意:核心方法
+-------------------+ +--------------------+
| Files.createFile | ----> | 新文件 |
+-------------------+ +--------------------+
+---------------------+ +--------------------+
| Files.createDirectory|----> | 新目录 |
+---------------------+ +--------------------+
+-------------------+ +--------------------+
| Files.delete | ----> | 文件/目录已删除 |
+-------------------+ +--------------------+
(但前提是目录为空!)
6. 创建与删除文件和目录的常见错误
错误 1:尝试创建已存在的文件/目录。 Files.createFile 和 Files.createDirectory 在对象已存在时会抛出异常。解决方案——提前检查是否存在或捕获异常。
错误 2:使用 createDirectory 创建嵌套目录,但父目录尚不存在。 此时会抛出 NoSuchFileException。请使用 createDirectories 来创建目录链。
错误 3:尝试通过 Files.delete 删除非空目录。 会得到 DirectoryNotEmptyException。删除非空目录需要递归。
错误 4:没有在指定目录中创建/删除的权限。 将抛出 AccessDeniedException 或 IOException。以所需权限运行程序或使用可访问的目录。
错误 5:文件被其他进程占用。 在 Windows(以及有时其他操作系统)上,如果文件被其他程序打开,将无法删除。你会得到 IOException。请在删除前关闭所有使用该文件的应用。
错误 6:在不清楚“当前工作目录”时使用相对路径。 文件会被创建在与你预期不同的位置。为了确定,请使用 toAbsolutePath() 并将路径打印出来。
GO TO FULL VERSION