1. 概述

在这个快速教程中,我们将学习如何在Java中将文件转换为字节数组。

首先,我们会了解使用Java内置解决方案的方法。接着,我们将讨论如何使用Apache Commons IO和Guava库实现相同的结果。

2. 使用Java

Java开发工具包(JDK)提供了多种方便的方式将文件转换为字节数组。例如,我们可以利用java.iojava.nio包来回答核心问题。现在,让我们深入研究每个选项。

2.1. FileInputStream

我们从java.io包中的FileInputStream类开始。通常,这个类提供了读取文件内容作为字节的方法。

假设我们有一个名为sample.txt的文件,内容是"Hello World"

class FileToByteArrayUnitTest {

    private static final String FILE_NAME = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "sample.txt";
    private final byte[] expectedByteArray = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 };

    @Test
    void givenFile_whenUsingFileInputStreamClass_thenConvert() throws IOException {
        File myFile = new File(FILE_NAME);
        byte[] byteArray = new byte[(int) myFile.length()];
        try (FileInputStream inputStream = new FileInputStream(myFile)) {
            inputStream.read(byteArray);
        }

        assertArrayEquals(expectedByteArray, byteArray);
    }
}

这里,我们使用给定的sample.txt文件创建了一个FileInputStream实例。然后,我们调用read(byte[] b)方法,将数据从FileInputStream实例读入定义的字节数组中。

值得注意的是,我们使用了try-with-resources语句来高效地处理资源关闭。

2.2. Files#readAllBytes

另一种选择是使用java.nio API的Files类。顾名思义,这个实用工具类提供了多个现成的静态方法来处理文件和目录。

让我们看看它的操作:

@Test
void givenFile_whenUsingNioApiFilesClass_thenConvert() throws IOException {
    byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));

    assertArrayEquals(expectedByteArray, byteArray);
}

如图所示,Files类提供了readAllBytes()方法,该方法从指定路径文件返回所有字节。有趣的是,当读取完字节后,此方法会自动关闭文件

另一个重要注意事项是,这个方法不适用于读取大型文件。因此,我们只适用于简单情况。

3. 使用Apache Commons IO

另一种解决方案是使用Apache Commons IO库。它提供了一系列方便的实用类,用于执行常见的I/O任务。

首先,我们需要在pom.xml文件中添加commons-io依赖项

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

3.1. FileUtils#readFileToByteArray

FileUtils类,顾名思义,提供了一套文件操作方法。其中,我们找到了readFileToByteArray()方法:

@Test
void givenFile_whenUsingApacheCommonsFileUtilsClass_thenConvert() throws IOException {
    byte[] byteArray = FileUtils.readFileToByteArray(new File(FILE_NAME));

    assertArrayEquals(expectedByteArray, byteArray);
}

如上所述,readFileToByteArray()方法以直接的方式将指定文件的内容读取到字节数组中。这个方法的优点是文件始终会被关闭。

此外,这个方法没有Files#readAllBytes的限制,并且如果提供的文件为null,它会抛出NullPointerException

3.2. IOUtils#toByteArray

Apache Commons IO还提供了另一种实现相同效果的方法。它提供了IOUtils类来处理通用的I/O流操作。

让我们通过一个实际例子来演示IOUtils的使用:

@Test
void givenFile_whenUsingApacheCommonsIOUtilsClass_thenConvert() throws IOException {
    File myFile = new File(FILE_NAME);
    byte[] byteArray = new byte[(int) myFile.length()];
    try (FileInputStream inputStream = new FileInputStream(myFile)) {
        byteArray = IOUtils.toByteArray(inputStream);
    }

    assertArrayEquals(expectedByteArray, byteArray);
}

简而言之,IOUtils类提供了toByteArray()方法,将InputStream的数据作为byte[]返回。这里不需要使用BufferedInputStream,因为该方法内部会进行内容缓冲。

4. 使用Guava

当你需要将文件转换为字节数组时,还可以考虑使用Guava库。像往常一样,在开始使用此库之前,我们需要将其依赖项添加到pom.xml

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

4.1. Files#toByteArray

Guava库提供了自己的Files类版本。让我们看看它的应用:

@Test
void givenFile_whenUsingGuavaFilesClass_thenConvert() throws IOException {
    byte[] byteArray = com.google.common.io.Files.toByteArray(new File(FILE_NAME));

    assertArrayEquals(expectedByteArray, byteArray);
}

简言之,我们使用toByteArray()方法获取包含给定文件所有字节的字节数组。

5. 总结

在这篇短文中,我们探讨了使用JDK方法、Guava和Apache Commons IO库将文件转换为字节数组的各种方式。

如往常一样,本文中使用的代码可以在GitHub上找到。