1. 概述

在Java应用中,我们经常需要处理文件操作。有时,我们需要在进行进一步操作之前检查文件是否为空。本教程将探讨几种高效且直观的方法,用于在Java中判断文件是否为空。

2. 问题介绍

在深入实现之前,让我们理解一下文件为空的含义。

在文件操作的上下文中,空文件是指不包含任何数据或大小为零字节的文件

当涉及到读取或解析文件等输入输出操作时,验证文件是否为空特别有用。

Java标准库提供了获取文件大小的方法,但我们需要留意一些陷阱

为了简化,我们将使用单元测试断言来验证我们的方法是否按预期工作。此外,JUnit 5的TempDirectory扩展使我们在单元测试中轻松创建和清理临时目录。由于我们的测试与文件相关,我们将使用这个扩展来支持我们的验证。

3. 使用File.length()方法

我们知道,我们可以通过检查文件的大小来确定它是否为空。Java标准I/O库提供了**File.length()方法来计算文件的字节数**。

因此,我们可以通过检查File.length()是否返回0来解决问题:

@Test
void whenTheFileIsEmpty_thenFileLengthIsZero(@TempDir Path tempDir) throws IOException {
    File emptyFile = tempDir.resolve("an-empty-file.txt")
      .toFile();
    emptyFile.createNewFile();
    assertTrue(emptyFile.exists());
    assertEquals(0, emptyFile.length());
}

通过File.length()检查文件是否为空很方便。但存在一个陷阱。让我们通过另一个测试来理解:

@Test
void whenFileDoesNotExist_thenFileLengthIsZero(@TempDir Path tempDir) {
    File aNewFile = tempDir.resolve("a-new-file.txt")
      .toFile();
    assertFalse(aNewFile.exists());
    assertEquals(0, aNewFile.length());
}

在这个测试中,我们像往常一样初始化了一个File对象,但没有创建文件。换句话说,文件tempDir/a-new-file.txt并不存在

所以测试显示,当我们对一个不存在的文件调用File.length()时,它也会返回0。通常,当我们谈论文件为空时,文件必须存在。因此,仅依赖File.length()来判断文件是否为空是不可靠的。

接下来,让我们创建一个方法来解决这个问题:

boolean isFileEmpty(File file) {
    if (!file.exists()) {
        throw new IllegalArgumentException("Cannot check the file length. The file is not found: " + file.getAbsolutePath());
    }
    return file.length() == 0;
}

在上述方法中,如果文件不存在,我们会抛出IllegalArgumentException。有人可能会认为应该使用FileNotFoundException。这里我们没有选择FileNotFoundException,因为它是一个检查异常。如果我们调用isFileEmpty()方法时抛出这个异常,我们必须处理异常。另一方面,IllegalArgumentException是未检查异常,表示file参数无效。

现在,isFileEmpty()方法无论文件是否存在都能正常工作:

@Test
void whenTheFileDoesNotExist_thenIsFilesEmptyThrowsException(@TempDir Path tempDir) {
    File aNewFile = tempDir.resolve("a-new-file.txt")
      .toFile();
    IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> isFileEmpty(aNewFile));
    assertEquals(ex.getMessage(), "Cannot check the file length. The file is not found: " + aNewFile.getAbsolutePath());
}

@Test
void whenTheFileIsEmpty_thenIsFilesEmptyReturnsTrue(@TempDir Path tempDir) throws IOException {
    File emptyFile = tempDir.resolve("an-empty-file.txt")
      .toFile();
    emptyFile.createNewFile();
    assertTrue(isFileEmpty(emptyFile));
}

4. 使用NIO的Files.size()方法

我们已经使用File.length()解决了问题。

File.length()来自Java标准I/O。另外,如果我们使用的是Java 7或更高版本,我们可以使用Java NIO API来解决这个问题。例如,java.nio.file.Files.size()返回文件的大小,也可以帮助我们检查文件是否为空。

值得一提的是,**如果文件不存在,Java NIO的Files.size()会抛出NoSuchFileException**:

@Test
void whenTheFileIsEmpty_thenFilesSizeReturnsTrue(@TempDir Path tempDir) throws IOException {
    Path emptyFilePath = tempDir.resolve("an-empty-file.txt");
    Files.createFile(emptyFilePath);
    assertEquals(0, Files.size(emptyFilePath));
}

@Test
void whenTheFileDoesNotExist_thenFilesSizeThrowsException(@TempDir Path tempDir) {
    Path aNewFilePath = tempDir.resolve("a-new-file.txt");
    assertThrows(NoSuchFileException.class, () -> Files.size(aNewFilePath));
}

5. 总结

在这篇文章中,我们探讨了两种在Java中检查文件是否为空的方法:

  • 使用Java标准I/O的File.length()
  • 使用Java NIO的Files.size()

如往常一样,文章中展示的所有代码片段可在GitHub上找到:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-io-apis-2