Java中实现拷贝文件
本文我们学习java中多种方式复制文件。首先使用标准IO和NIO2 api,然后利用第三方库实现。
IO API
首先,使用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())));
}
实现这个基本功能确实够费力。幸运的是,java nio2中提供更简单方式实现拷贝功能。
NIO2 API
使用NOI2 可以显著提升拷贝性能,因为NIO2利用系统底层功能。让我们详细看看如何利用File.copy方法。copy方法可以指定拷贝选项参数。默认情况下,拷贝文件或目录不覆盖已存在的文件或目录,也不拷贝文件属性。但可以通过下面拷贝属性进行设置:
- REPLACE_EXISTING – 如果存在则覆盖
- COPY_ATTRIBUTES – 拷贝元信息至新的文件
- NOFOLLOW_LINKS – 不包含符号链接的文件
NIO2的Files类提供一组copy方法,用于拷贝文件和目录。请看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)));
}
注意目录拷贝是浅拷贝,意味着目录中的文件和子目录不被拷贝。
使用Apache Commons IO库
Apache Commons IO库中FileUtils类也提供了copyFile方法,需要源和目标两个参数。请看示例:
@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())));
}
使用Guava库
最后我们看看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())));
}
总结
本文我们学习了多种方式在java复制文件或目录。