1. Overview
1.概述
In this article, we’ll cover common ways of copying files in Java.
在这篇文章中,我们将介绍在Java中复制文件的常见方法。
First, we’ll use the standard IO and NIO.2 APIs, and two external libraries: commons-io and guava.
首先,我们将使用标准的IO和NIO.2 API,以及两个外部库。commons-io和guava。
2. IO API (Before JDK7)
2.IO API(JDK7之前)
First of all, to copy a file with java.io API, we’re required to open a stream, loop through the content and write it out to another stream:
首先,要用java.io API复制一个文件,我们需要打开一个流,循环浏览内容并将其写入另一个流中:
@Test
public void givenIoAPI_whenCopied_thenCopyExistsWithSameContents()
throws IOException {
File copied = new File("src/test/resources/copiedWithIo.txt");
try (
InputStream in = new BufferedInputStream(
new FileInputStream(original));
OutputStream out = new BufferedOutputStream(
new FileOutputStream(copied))) {
byte[] buffer = new byte[1024];
int lengthRead;
while ((lengthRead = in.read(buffer)) > 0) {
out.write(buffer, 0, lengthRead);
out.flush();
}
}
assertThat(copied).exists();
assertThat(Files.readAllLines(original.toPath())
.equals(Files.readAllLines(copied.toPath())));
}
Quite a lot of work to implement such basic functionality.
要实现这样的基本功能需要做很多工作。
Luckily for us, Java has improved its core APIs and we have a simpler way of copying files using NIO.2 API.
幸运的是,Java已经改进了它的核心API,我们有一个更简单的方法来使用NIO.2 API复制文件。
3. NIO.2 API (JDK7)
3.NIO.2 API(JDK7)
Using NIO.2 can significantly increase file copying performance since the NIO.2 utilizes lower-level system entry points.
使用NIO.2可以显著提高文件复制性能,因为NIO.2利用了较低级别的系统入口点。
Let’s take a closer look at how the Files.copy() method works.
让我们仔细看看Files.copy()方法是如何工作的。
The copy() method gives us the ability to specify an optional argument representing a copy option. By default, copying files and directories won’t overwrite existing ones, nor will it copy file attributes.
copy()方法让我们能够指定一个代表复制选项的可选参数。默认情况下,复制文件和目录不会覆盖现有文件,也不会复制文件属性。
This behavior can be changed using the following copy options:
这种行为可以通过以下复制选项来改变。
- REPLACE_EXISTING – replace a file if it exists
- COPY_ATTRIBUTES – copy metadata to the new file
- NOFOLLOW_LINKS – shouldn’t follow symbolic links
The NIO.2 Files class provides a set of overloaded copy() methods for copying files and directories within the file system.
NIO.2文件类提供了一组重载的copy()方法,用于在文件系统中复制文件和目录。
Let’s take a look at an example using copy() with two Path arguments:
让我们看看一个使用copy()的例子,有两个Path参数。
@Test
public void givenNIO2_whenCopied_thenCopyExistsWithSameContents()
throws IOException {
Path copied = Paths.get("src/test/resources/copiedWithNio.txt");
Path originalPath = original.toPath();
Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
assertThat(copied).exists();
assertThat(Files.readAllLines(originalPath)
.equals(Files.readAllLines(copied)));
}
Note that directory copies are shallow, meaning that files and sub-directories within the directory are not copied.
注意,目录复制是浅层的,意味着目录内的文件和子目录不会被复制。
4. Apache Commons IO
4.Apache Commons IO
Another common way to copy a file with Java is by using the commons-io library.
用Java复制文件的另一个常用方法是使用commons-io库。
First, we need to add the dependency:
首先,我们需要添加依赖关系。
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
The latest version can be downloaded from Maven Central.
最新版本可以从Maven中心下载。
Then, to copy a file we just need to use the copyFile() method defined in the FileUtils class. The method takes a source and a target file.
然后,为了复制一个文件,我们只需要使用copyFile()类中定义的FileUtils方法。该方法需要一个源文件和一个目标文件。
Let’s take a look at a JUnit test using the copyFile() method:
让我们看一下使用copyFile()方法的JUnit测试。
@Test
public void givenCommonsIoAPI_whenCopied_thenCopyExistsWithSameContents()
throws IOException {
File copied = new File(
"src/test/resources/copiedWithApacheCommons.txt");
FileUtils.copyFile(original, copied);
assertThat(copied).exists();
assertThat(Files.readAllLines(original.toPath())
.equals(Files.readAllLines(copied.toPath())));
}
5. Guava
5 番石榴
Finally, we’ll take a look at Google’s Guava library.
最后,我们将看一下谷歌的Guava库。
Again, if we want to use Guava, we need to include the dependency:
同样,如果我们想使用Guava,我们需要包含这个依赖关系。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
The latest version can be found on Maven Central.
最新版本可以在Maven中心找到。
And here’s the Guava’s way of copying a file:
这里是Guava复制文件的方式。
@Test
public void givenGuava_whenCopied_thenCopyExistsWithSameContents()
throws IOException {
File copied = new File("src/test/resources/copiedWithGuava.txt");
com.google.common.io.Files.copy(original, copied);
assertThat(copied).exists();
assertThat(Files.readAllLines(original.toPath())
.equals(Files.readAllLines(copied.toPath())));
}
6. Conclusion
6.结论
In this article, we explored the most common ways to copy a file in Java.
在这篇文章中,我们探讨了在Java中复制文件的最常见方法。
The full implementation of this article can be found over on Github.
本文的完整实现可以在Github上找到over。