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复制文件或目录。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐