В классе 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.



