Перейти к основному содержимому

Как скопировать файл с помощью Java

· 3 мин. чтения

1. Обзор

В этой статье мы рассмотрим распространенные способы копирования файлов в Java.

Во-первых, мы будем использовать стандартные API-интерфейсы IO и NIO.2 , а также две внешние библиотеки: commons-io и guava .

2. API ввода -вывода (до JDK7)

Прежде всего, чтобы скопировать файл с помощью 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 улучшила свои основные API, и у нас есть более простой способ копирования файлов с помощью NIO.2 API .

3. API NIO.2 (JDK7)

Использование NIO.2 может значительно повысить производительность копирования файлов, поскольку NIO.2 использует точки входа в систему более низкого уровня.

Давайте подробнее рассмотрим, как работает Files. Метод copy() работает.

Метод copy() дает нам возможность указать необязательный аргумент, представляющий параметр копирования. По умолчанию копирование файлов и каталогов не перезаписывает существующие и не копирует атрибуты файлов.

Это поведение можно изменить с помощью следующих параметров копирования:

  • REPLACE_EXISTING — заменить файл, если он существует
  • COPY_ATTRIBUTES — скопировать метаданные в новый файл
  • NOFOLLOW_LINKS — не следует переходить по символическим ссылкам

Класс NIO.2 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)));
}

Обратите внимание, что копии каталогов являются неглубокими , то есть файлы и подкаталоги внутри каталога не копируются.

4. Apache Commons IO

Другой распространенный способ скопировать файл с помощью Java — использовать библиотеку commons-io .

Во-первых, нам нужно добавить зависимость:

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

Последнюю версию можно скачать с Maven Central .

Затем, чтобы скопировать файл, нам просто нужно использовать метод copyFile() , определенный в классе FileUtils . Метод принимает исходный и целевой файл.

Давайте взглянем на тест JUnit с использованием метода 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())));
}

5. Гуава

Наконец, мы взглянем на библиотеку Google Guava.

Опять же, если мы хотим использовать Guava , нам нужно включить зависимость:

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

Последнюю версию можно найти на Maven Central .

А вот способ копирования файла в Гуаве:

@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. Заключение

В этой статье мы рассмотрели наиболее распространенные способы копирования файла в Java.

Полную реализацию этой статьи можно найти на Github.