1. 概述

本文将快速介绍在 Java 中创建文件的几种常用方法。我们会依次使用 NIO 的 FilesPath 类、传统的 FileFileOutputStream 类,以及第三方库 Google Guava 和 Apache Commons IO 来实现文件创建。

这些方法各有特点,适用于不同场景。掌握它们有助于你在实际开发中灵活选择,避免踩坑。


2. 环境准备

在所有示例中,我们统一使用一个常量来定义目标文件路径:

private final String FILE_NAME = "src/test/resources/fileToCreate.txt";

为了保证每个测试用例的独立性,我们在每次测试前后清理目标文件:

@AfterEach
@BeforeEach
public void cleanUpFiles() {
    File targetFile = new File(FILE_NAME);
    targetFile.delete();
}

✅ 这种做法能有效避免测试之间的干扰,是单元测试中的常见实践。


3. 使用 NIO Files.createFile()

最推荐的方式之一是使用 Java NIO 的 Files.createFile() 方法:

@Test
public void givenUsingNio_whenCreatingFile_thenCorrect() throws IOException {
    Path newFilePath = Paths.get(FILE_NAME);
    Files.createFile(newFilePath);
}

特点:

  • ✅ 基于现代 NIO API,语义清晰
  • ✅ 自动利用 Path 接口处理路径,更安全
  • ❌ 如果文件已存在,会抛出异常

⚠️ 注意:如果目标文件已经存在,该方法会抛出 FileAlreadyExistsException,而不是静默失败:

java.nio.file.FileAlreadyExistsException: src/test/resources/fileToCreate.txt 
    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:81)

📌 适用场景:你希望明确知道文件是否被成功创建,且不希望覆盖已有文件时。


4. 使用 File.createNewFile()

这是传统 IO 包中最直接的方式:

@Test
public void givenUsingFile_whenCreatingFile_thenCorrect() throws IOException {
    File newFile = new File(FILE_NAME);
    boolean success = newFile.createNewFile();
    assertTrue(success);
}

关键行为:

  • ✅ 仅当文件不存在时创建,存在则返回 false
  • ❌ 不抛异常,需手动检查返回值
  • ⚠️ 方法是原子操作,适合多线程环境下的“首次创建”逻辑

📌 典型用途:实现简单的“锁文件”机制或确保某个配置文件只被初始化一次。


5. 使用 FileOutputStream

通过构造 FileOutputStream 实例也可以间接创建文件:

@Test
public void givenUsingFileOutputStream_whenCreatingFile_thenCorrect() throws IOException {
    try (FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)) {
        // 文件在此时已被创建
    }
}

行为说明:

  • ✅ 文件不存在时自动创建
  • 如果文件已存在,内容会被清空(覆盖)
  • ❌ 若目标路径是目录或无权限,抛出 FileNotFoundException
  • ✅ 使用 try-with-resources 确保资源释放

📌 风险提示:这种方式容易误删已有数据,使用时务必确认业务逻辑是否允许覆盖。


6. 使用 Guava

Google Guava 提供了极为简洁的工具方法:

@Test
public void givenUsingGuava_whenCreatingFile_thenCorrect() throws IOException {
    com.google.common.io.Files.touch(new File(FILE_NAME));
}

优势:

  • ✅ 一行代码搞定
  • ✅ 若文件已存在,仅更新时间戳,不报错
  • ✅ 支持递归创建父目录

📌 适合场景:脚本化任务、临时文件初始化等对健壮性要求高的地方。


7. 使用 Apache Commons IO

Apache Commons IO 同样提供了类似功能:

@Test
public void givenUsingCommonsIo_whenCreatingFile_thenCorrect() throws IOException {
    FileUtils.touch(new File(FILE_NAME));
}

行为特点:

  • ✅ 功能与 Guava 的 touch 基本一致
  • ✅ 自动创建缺失的父目录
  • ✅ 文件存在时不报错,仅更新最后修改时间

📌 对比建议

  • 如果项目已引入 Commons IO,优先使用 FileUtils.touch()
  • 否则不必为了一个功能引入新依赖

8. 总结

方法 是否覆盖 异常处理 是否创建父目录 推荐指数
Files.createFile() ❌ 抛异常 ✅ 明确 ❌ 需手动 ⭐⭐⭐⭐
File.createNewFile() ❌ 返回 false ❌ 需判断 ⭐⭐⭐
FileOutputStream ✅ 覆盖 ✅ 抛异常 ⭐⭐⭐
Guava Files.touch() ❌ 不覆盖 ✅ 安静处理 ⭐⭐⭐⭐⭐
Commons IO FileUtils.touch() ❌ 不覆盖 ✅ 安静处理 ⭐⭐⭐⭐⭐

最终建议:

  • 日常开发中,✅ 优先考虑 Guava 或 Commons IO 的 touch 方法,简单粗暴又安全。
  • 若不能引入第三方库,使用 Files.createFile() + Files.createDirectories() 组合也能达到类似效果。

示例代码已托管至 GitHub:https://github.com/baeldung/java-tutorials(模块:core-java-io-3)


原始标题:Java - Create a File | Baeldung