CodeGym /课程 /JAVA 25 SELF /目录操作:创建、删除、查看内容

目录操作:创建、删除、查看内容

JAVA 25 SELF
第 35 级 , 课程 4
可用

1. 创建目录

目录(也称“文件夹”)— 这不仅仅是文件的容器,而是磁盘上数据组织的基础。在应用中我们经常为输入/输出数据、日志、临时文件等创建目录。现代 API java.nio.file 让这一切变得方便且跨平台。

让我们看看如何通过 FilesPathPaths 创建、删除并查看文件夹内容。

Files.createDirectory(path)

创建一个目录到指定路径。如果父目录不存在—将抛出异常。

import java.nio.file.*;

public class DirectoryDemo {
    public static void main(String[] args) throws Exception {
        Path dir = Paths.get("testDir");
        if (!Files.exists(dir)) {
            Files.createDirectory(dir);
            System.out.println("目录已创建:" + dir.toAbsolutePath());
        } else {
            System.out.println("目录已存在:" + dir.toAbsolutePath());
        }
    }
}

如果尝试创建已存在的目录,会得到 FileAlreadyExistsException

Files.createDirectories(path)

创建整条目录链。如果某些中间目录不存在—会自动创建;若部分已经存在—不会报错。

Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("已创建目录链:" + nestedDir.toAbsolutePath());

这就像让 Java 不仅建房子,还把单元楼和街道都建出来,如果它们还不存在的话。

典型示例:为项目创建目录结构

假设需要将报表保存到文件夹 output/reports/2024。不要手动逐级检查每个目录—使用 createDirectories

Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);

Java 会自动判断哪些已存在,哪些需要创建。

2. 删除文件和目录

Files.delete(path)

删除文件或目录。如果目录非空—将抛出 DirectoryNotEmptyException

Path dir = Paths.get("testDir");
try {
    Files.delete(dir);
    System.out.println("目录已删除:" + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
    System.out.println("无法删除:目录非空!");
}

Files.deleteIfExists(path)

作用与 delete 类似,但当对象不存在时不会抛错。若确实删除了内容返回 true,如果对象不存在返回 false

Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
    System.out.println("文件已删除。");
} else {
    System.out.println("未找到文件,未执行任何删除。");
}

如何删除非空目录?

不能直接删除非空文件夹。需要先删除其所有内容(文件和子目录),然后再删除文件夹本身。可以递归完成,例如通过 Files.walkFileTree

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class DeleteDirectoryRecursively {
    public static void main(String[] args) throws IOException {
        Path dir = Paths.get("parent");
        if (Files.exists(dir)) {
            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
            System.out.println("目录及其所有内容已删除。");
        }
    }
}

如果你刚开始,不要被这段代码吓到—稍后我们会更详细地讲解 walkFileTree

3. 查看目录内容

Files.list(path)

返回 Stream<Path>—路径流。你可以通过 Stream API 处理文件夹内容。每个条目是文件或子目录(不递归!)。

Path dir = Paths.get("output/reports");
if (Files.exists(dir) && Files.isDirectory(dir)) {
    try (var stream = Files.list(dir)) {
        stream.forEach(path -> System.out.println(path.getFileName()));
    }
}

重要细节:流一定要关闭,因此我们使用 try‑with‑resources。

示例:输出文件和子目录的名称

Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
    stream.forEach(path -> {
        String type = Files.isDirectory(path) ? "目录" : "文件";
        System.out.println(path.getFileName() + " — " + type);
    });
}

以集合形式获取文件列表

List<Path> files = Files.list(reports2024)
    .filter(Files::isRegularFile)
    .toList();

System.out.println("文件列表:");
files.forEach(System.out::println);

重要:Files.list(path) 只返回当前目录(顶层)的内容。要递归遍历请使用 Files.walk(path)

4. 实战:迷你文件管理器

该工具会创建目录 mydata/logs、文件 log1.txt,打印文件夹内容,然后全部删除。

import java.nio.file.*;
import java.io.IOException;

public class MiniFileManager {
    public static void main(String[] args) throws IOException {
        Path logsDir = Paths.get("mydata/logs");
        Files.createDirectories(logsDir);

        Path logFile = logsDir.resolve("log1.txt");
        Files.writeString(logFile, "Hello, log!");

        System.out.println("文件夹 " + logsDir + " 的内容:");
        try (var stream = Files.list(logsDir)) {
            stream.forEach(path -> System.out.println(" - " + path.getFileName()));
        }

        Files.deleteIfExists(logFile);
        Files.deleteIfExists(logsDir);
        System.out.println("文件和文件夹已删除。");
    }
}

代码说明:

  • Files.createDirectories 确保整条目录链都会被创建。
  • resolve 是在路径后追加文件名的便捷方式。
  • 通过 try‑with‑resources 关闭来自 Files.list 的流—在 Windows 上尤其重要。

5. 特性与注意事项

检查是否存在

在创建/删除之前,最好先检查路径是否存在:

if (!Files.exists(path)) {
    Files.createDirectory(path);
}

访问权限

如果程序没有创建/删除的权限—会得到 AccessDeniedException。例如,以普通用户身份在磁盘根目录创建文件夹几乎总会失败。

空目录与非空目录

只能删除空目录(Files.delete)。要连同内容一起删除请使用递归遍历(walkFileTree)。

跨平台性

API java.nio.file 能在所有主流操作系统上正确工作并考虑路径分隔符。构建路径请使用 Paths.getPath.resolve,不要拼接字符串。

符号链接

在基础任务中可以不考虑它们,但如果遇到既不是普通文件也不是目录的“异常”条目—可能是符号链接。它们会在进阶讲解中再回到。

6. 操作目录时的常见错误

错误 1:试图通过 Files.delete(path) 直接删除非空目录。 Java 会抛出 DirectoryNotEmptyException。先删除内容,再删除文件夹本身。

错误 2:忘记关闭来自 Files.list() 的流。 如果不使用 try‑with‑resources,流会保持打开状态,在 Windows 上删除文件夹时可能报错。

错误 3:在未检查父目录是否存在的情况下创建目录。 当路径为 parent/childparent 不存在时调用 Files.createDirectory,会导致 NoSuchFileException。请使用 Files.createDirectories

错误 4:不必要地使用绝对路径。 在项目中应优先使用相对路径—这样代码可移植性更好。

错误 5:未处理 IOException 任何与文件系统的操作都可能失败。请用 try-catch 包裹,或将异常向上抛出。

错误 6:在无权限的目录中尝试创建/删除。 在这种情况下会得到 AccessDeniedException。请检查运行上下文和访问权限。

1
调查/小测验
文件操作第 35 级,课程 4
不可用
文件操作
文件操作
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION