В классе java.io.File нет ни одного метода скопировать файл с одного места в другое. Поэтому в этой статье мы рассмотрим несколько наиболее используемых способов копирования файла.
Способ 1: Используем потоки для копирования файла
Этот способ является наиболее используемым. Его суть состоит в следующем: создаем два файла (что копировать и куда копировать файл). Затем создаем InputStream
от источника и записать его в результирующий файл-копию с использованием OutputStream
.
Ниже представлен метод на Java для копирования файла с использованием потоков:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
private static void copyFileUsingStream(File source, File dest) throws IOException { InputStream is = null; OutputStream os = null; try { is = new FileInputStream(source); os = new FileOutputStream(dest); byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) > 0) { os.write(buffer, 0, length); } } finally { is.close(); os.close(); } } |
Способ 2: Используем FileChannel
Для копирования файла также можно использовать java.nio.channels.FileChannel
. В этом классе есть очень полезный метод transferFrom()
, который также очень часто используется для копирования файлов. Согласно документации, этот способ копирования файла работает быстрее, чем при использовании потоков (InputStream,
OutputStream
).
Ниже приведен метод копирования файлов с помощью класса FileChannel
:
1 2 3 4 5 6 7 8 9 10 11 12 |
private static void copyFileUsingChannel(File source, File dest) throws IOException { FileChannel sourceChannel = null; FileChannel destChannel = null; try { sourceChannel = new FileInputStream(source).getChannel(); destChannel = new FileOutputStream(dest).getChannel(); destChannel.transferFrom(sourceChannel, 0, sourceChannel.size()); }finally{ sourceChannel.close(); destChannel.close(); } } |
Способ 3: Используем Apache Commons IO
В Apache Commons IO
есть отличный класс FileUtils
с методом copyFile(File srcFile, File destFile)
может быть использован для копирования файла в Java. Если вы уже используете Apache Commons IO
в вашем проекте, то есть смысл использовать метод copyFile(File srcFile, File destFile)
для простоты и удобства кода. Внутри себя он использует NIO FileChannel
, предоставляя программисту лишь удобную оболочку.
Ниже приведен пример использования Apache Commons IO
для копирования файлов в Java.
1 2 3 4 |
// вот такой простой метод метод копирования файла private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException { FileUtils.copyFile(source, dest); } |
Способ 4: Используем класс Files (начиная с Java 7)
Класс Files
был введен в Java 7 и предоставляет метод copy()
для копирования файла. Он использует встроенные возможности системы, чтобы скопировать файл.
1 2 3 4 |
// простой и удобный метод копирования файла в Java 7 private static void copyFileUsingJava7Files(File source, File dest) throws IOException { Files.copy(source.toPath(), dest.toPath()); } |
Какой метод копирования файла в Java самый лучший?
Так какой же метод копирования файла в Java является наиболее быстрым и эффективным? Для теста были использованы разные файлы размером 1Gb.
Я решил проверить быстродействие каждого метода копирования файла и написал вот такой класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package ua.com.prologistic; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.FileChannel; import java.nio.file.Files; import org.apache.commons.io.FileUtils; public class JavaCopyFile { public static void main(String[] args) throws InterruptedException, IOException { File source = new File("/Users/prologistic/tmp/source.avi"); File dest = new File("/Users/prologistic/tmp/dest.avi"); // копируем файл с помощью потоков long start = System.nanoTime(); // засекаем время до выполнения копирования copyFileUsingStream(source, dest); System.out.println("Время копирования файла с помощью потоков = "+(System.nanoTime()-start)); // копируем файл с помощью java.nio.FileChannel source = new File("/Users/prologistic/tmp/sourceChannel.avi"); dest = new File("/Users/prologistic/tmp/destChannel.avi"); start = System.nanoTime(); copyFileUsingChannel(source, dest); System.out.println("Время копирования файла с помощью java.nio.FileChannel = "+(System.nanoTime()-start)); // копируем файл с помощью Apache Commons io source = new File("/Users/prologistic/tmp/sourceApache.avi"); dest = new File("/Users/prologistic/tmp/destApache.avi"); start = System.nanoTime(); copyFileUsingApacheCommonsIO(source, dest); System.out.println("Время копирования файла с помощью Apache Commons IO Copy = "+(System.nanoTime()-start)); // копируем файл с помощью класса Files (Java 7) source = new File("/Users/prologistic/tmp/sourceJava7.avi"); dest = new File("/Users/prologistic/tmp/destJava7.avi"); start = System.nanoTime(); copyFileUsingJava7Files(source, dest); System.out.println("Время копирования файла с помощью класса Files Java 7 = "+(System.nanoTime()-start)); } } |
Результат выполнения программы:
1 2 3 4 |
Время копирования файла с помощью потоков = 44373464300 Время копирования файла с помощью java.nio.FileChannel = 105216373000 Время копирования файла с помощью Apache Commons IO Copy = 106275636000 Время копирования файла с помощью класса Files Java 7 = 97353457000 |
По результатам выполнения программы видно, что лучшим способом копирования файла в Java является использование потоков, то есть первого способа в нашей подборке.
Следует отметить, что в ходе разработки разных проектов на Java, все-таки желательно использовать разные методы копирования файлов. Дело в том, что многое зависит от количества файлов и их размера. В нашем случае мы тестировали файлы размером 1Gb.