1. Обзор
В этой статье мы рассмотрим распространенные способы копирования файлов на Java.
Во-первых, мы будем использовать стандартные IO и NIO.2 API и две внешние библиотеки: commons-io и guava .
2. API ВВОДА-вывода (До JDK 7)
Прежде всего, чтобы скопировать файл с 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. НИО.2 API (JDK 7)
С помощью НИО.2 может значительно повысить производительность копирования файлов, так как НИО.2 использует точки входа в систему более низкого уровня.
Давайте подробнее рассмотрим, как работают файлы. copy() метод работает.
Метод copy() дает нам возможность указать необязательный аргумент, представляющий параметр копирования. По умолчанию копирование файлов и каталогов не перезаписывает существующие, а также не копирует атрибуты файлов.
Это поведение можно изменить с помощью следующих параметров копирования:
- REPLACE_EXISTING – заменить файл, если он существует
- COPY_ATTRIBUTES – копирование метаданных в новый файл
- NOFOLLOW_LINKS – не следует переходить по символическим ссылкам
НИО.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 .
Во-первых, нам нужно добавить зависимость:
commons-io commons-io 2.8.0
Последнюю версию можно загрузить с сайта 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 , нам нужно включить зависимость:
com.google.guava guava 23.0
Последнюю версию можно найти на 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.