Стандартный лаконичный способ скопировать файл на Java?

Меня всегда беспокоило, что единственный способ скопировать файл на Java - это открытие потоков, объявление буфера, чтение одного файла, его просмотр и запись в другой Steam. Интернет изобилует похожими, но все же немного разными реализациями этого типа решений.

Есть ли лучший способ, который не выходит за рамки языка Java (то есть не требует выполнения команд, специфичных для ОС)? Возможно, в каком-нибудь надежном пакете утилит с открытым исходным кодом это, по крайней мере, затмевает эту базовую реализацию и обеспечивает решение в одну строку?

Там могло быть что-то в Apache Commons FileUtils, в частности методы копировать файл.

toolkit 20.09.2008 06:04

Если вы используете Java 7, используйте вместо этого Files.copy, как рекомендовано @GlenBest: stackoverflow.com/a/16600787/44737

rob 18.06.2013 01:54
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
423
2
265 765
16
Перейти к ответу Данный вопрос помечен как решенный

Ответы 16

Ответ принят как подходящий

Как упоминалось выше в наборе инструментов, Apache Commons IO - это правильный выбор, в частности FileUtils.копировать файл(); он берет на себя всю тяжелую работу за вас.

И в качестве постскриптума обратите внимание, что в последних версиях FileUtils (например, в выпуске 2.0.1) добавлено использование NIO для копирования файлов; NIO может значительно повысить производительность копирования файлов, в значительной степени потому, что подпрограммы NIO откладывают копирование непосредственно в ОС / файловую систему, а не обрабатывают его путем чтения и записи байтов через уровень Java. Поэтому, если вы ищете производительность, возможно, стоит проверить, что вы используете последнюю версию FileUtils.

Очень полезно - знаете ли вы, когда в официальный выпуск войдут эти изменения nio?

Peter 20.09.2008 07:01

Понятия не имею ... Я просмотрел все источники общедоступной информации, которые смог найти, и нигде не упоминается о возможной дате выпуска. Однако сайт JIRA показывает только пять открытых проблем, так что, может быть, скоро?

delfuego 21.09.2008 06:04

Это тоже очень быстро, я заменил часть кода, который мы выполняли xCopy, чтобы скопировать некоторые каталоги, и это очень здорово увеличило скорость. (Я использовал версию из репозитория)

drye 01.10.2008 16:47

Публичный выпуск Apache Commons IO по-прежнему на уровне 1.4, grrrrrrr

Peter 03.09.2009 03:05

По состоянию на декабрь 2010 года Apache Commons IO находится на уровне 2.0.1, который имеет функциональность NIO. Ответ обновлен.

Simon Nickerson 08.04.2011 14:08

Предупреждение для пользователей Android: это НЕ входит в стандартные API Android.

IlDan 06.02.2012 14:46

Если вы используете Java 7 или новее, вы можете использовать Files.copy, как предлагает @GlenBest: stackoverflow.com/a/16600787/44737

rob 18.06.2013 01:57

Я бы избегал использования мега api, такого как apache commons. Это упрощенная операция, встроенная в JDK в новом пакете NIO. Это уже было связано с предыдущим ответом, но ключевым методом в API NIO являются новые функции «transferTo» и «transferFrom».

http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html#transferTo(long,%20long,%20java.nio.channels.WritableByteChannel)

В одной из связанных статей показано, как интегрировать эту функцию в ваш код с помощью transferFrom:

public static void copyFile(File sourceFile, File destFile) throws IOException {
    if (!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;

    try {
        source = new FileInputStream(sourceFile).getChannel();
        destination = new FileOutputStream(destFile).getChannel();
        destination.transferFrom(source, 0, source.size());
    }
    finally {
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }
}

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

Спасибо, полезная информация. Я бы все равно выступал за что-то вроде Apache Commons, особенно если он использует nio (правильно) под ним; но я согласен, что важно понимать основные принципы.

Peter 22.09.2008 21:19

Я согласен, что важно понимать предысторию nio, но я все равно выберу Jakarta Commons.

Ravi Wallau 05.03.2009 00:35

К сожалению, есть предостережения. Когда я скопировал файл размером 1,5 Гб в 32-битной Windows 7, он не смог сопоставить файл. Пришлось искать другое решение.

Anton K. 12.01.2011 11:48

Три возможных проблемы с приведенным выше кодом: (а) если getChannel выдает исключение, вы можете утечь открытый поток; (б) для больших файлов вы можете попытаться передать за один раз больше, чем может обработать ОС; (c) вы игнорируете возвращаемое значение transferFrom, поэтому возможно копирование только части файла. Вот почему org.apache.tools.ant.util.ResourceUtils.copyResource настолько сложен. Также обратите внимание, что хотя transferFrom в порядке, transferTo прерывается на JDK 1.4 в Linux: bugs.sun.com/bugdatabase/view_bug.do?bug_id=5056395

Jesse Glick 28.01.2011 03:41

Я считаю, что эта обновленная версия решает эти проблемы: gist.github.com/889747

Mark Renouf 28.03.2011 03:15

@Pete, похоже, Apache Commons еще не использует nio для копирования файлов.

An̲̳̳drew 29.06.2011 17:48

@Mark Renouf: Я получаю неоднозначные результаты с этим кодом. Не уверен, что происходит, но скопированные файлы иногда имеют нулевые байты.

James P. 15.08.2011 17:23

В этом коде есть проблема основной. transferTo () должен вызываться в цикле. Это не гарантирует перевод всей запрошенной суммы.

user207421 01.06.2013 05:30

@EJP Я больше не занимаюсь разработкой на Java. Возможно, вы правы, поэтому можете предложить правильный путь.

Josh 20.06.2013 03:13

В Windows Server я обнаружил, что файлы, скопированные таким образом с помощью NIO, не могут быть переименованы или удалены даже после вызова close () для всего. Я считаю, что это связано с отображениями памяти, которые создает NIO, требуя сборки мусора, как описано в эта почта.

foz 26.08.2014 15:39

Обратите внимание, что все эти механизмы копируют только содержимое файла, а не метаданные, такие как разрешения. Поэтому, если вы скопируете или переместите исполняемый файл .sh в Linux, новый файл не будет исполняемым.

Чтобы действительно скопировать или переместить файл, т.е. получить тот же результат, что и при копировании из командной строки, вам действительно нужно использовать собственный инструмент. Либо сценарий оболочки, либо JNI.

Судя по всему, это могло быть исправлено в java 7 - http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html. Скрещенные пальцы!

Доступно как стандарт в Java 7, path.copyTo: http://openjdk.java.net/projects/nio/javadoc/java/nio/file/Path.htmlhttp://java.sun.com/docs/books/tutorial/essential/io/copy.html

Не могу поверить, что им потребовалось так много времени, чтобы стандартизировать что-то настолько распространенное и простое, как копирование файлов :(

Нет Path.copyTo; это Files.copy.

Jesse Glick 03.03.2012 04:59

В библиотеке Google Guava также есть метод копирования:

public static void copy(File from,
                        File to)
                 throws IOException
Copies all the bytes from one file to another.

Предупреждение: Если to представляет существующий файл, этот файл будет перезаписан содержимым from. Если to и from относится к файлу одно и тоже, содержимое этого файла будет удален.

Параметры:from - исходный файл to - целевой файл

Броски:IOException - при возникновении ошибки ввода / вывода IllegalArgumentException - если from.equals(to)

Теперь с Java 7 вы можете использовать следующий синтаксис try-with-resource:

public static void copyFile( File from, File to ) throws IOException {

    if ( !to.exists() ) { to.createNewFile(); }

    try (
        FileChannel in = new FileInputStream( from ).getChannel();
        FileChannel out = new FileOutputStream( to ).getChannel() ) {

        out.transferFrom( in, 0, in.size() );
    }
}

Или, что еще лучше, это также можно сделать с помощью нового класса Files, представленного в Java 7:

public static void copyFile( File from, File to ) throws IOException {
    Files.copy( from.toPath(), to.toPath() );
}

Довольно шикарно, а?

Удивительно, что Java не добавляла подобных вещей до сегодняшнего дня. Определенные операции - это только самое необходимое для написания компьютерного программного обеспечения. Разработчики Oracle для Java могли бы кое-чему научиться у операционных систем, глядя на то, какие услуги они предоставляют, чтобы сделать миграцию новичков ЛЕГЧЕ.

Rick Hodgin 19.10.2011 02:30

Ах, спасибо! Я не знал о новом классе «Files» со всеми его вспомогательными функциями. В нем есть именно то, что мне нужно. Спасибо за пример.

ChrisCantrell 27.11.2012 04:26

с точки зрения производительности, java NIO FileChannel лучше, прочтите эту статью journaldev.com/861/4-ways-to-copy-file-in-java

Pankaj 04.12.2012 04:36

В этом коде есть проблема основной. transferTo () должен вызываться в цикле. Это не гарантирует перевод всей запрошенной суммы.

user207421 01.06.2013 05:30

@Scott: Пит попросил однострочное решение, и вы так близко ... нет необходимости заключать Files.copy в метод copyFile. Я бы просто поместил Files.copy (Path from, Path to) в начало вашего ответа и упомянул, что вы можете использовать File.toPath (), если у вас есть существующие объекты File: Files.copy (fromFile.toPath (), toFile.toPath ())

rob 18.06.2013 21:13

Три возможных проблемы с приведенным выше кодом:

  1. Если getChannel выдает исключение, может произойти утечка открытого потока.
  2. Для больших файлов вы, возможно, пытаетесь передать за один раз больше, чем может обработать ОС.
  3. Вы игнорируете возвращаемое значение transferFrom, поэтому оно может копировать только часть файла.

Вот почему org.apache.tools.ant.util.ResourceUtils.copyResource настолько сложен. Также обратите внимание, что хотя transferFrom в порядке, transferTo прерывается на JDK 1.4 в Linux (см. ID ошибки: 5056395) - Джесси Глик Ян

Если вы находитесь в веб-приложении, которое уже использует Spring, и если вы не хотите включать Apache Commons IO для простого копирования файлов, вы можете использовать FileCopyUtils среды Spring.

  • Эти методы ориентированы на производительность (они интегрируются с собственным вводом-выводом операционной системы).
  • Эти методы работают с файлами, каталогами и ссылками.
  • Каждая из поставляемых опций может быть опущена - они не являются обязательными.

Утилитарный класс

package com.yourcompany.nio;

class Files {

    static int copyRecursive(Path source, Path target, boolean prompt, CopyOptions options...) {
        CopyVisitor copyVisitor = new CopyVisitor(source, target, options).copy();
        EnumSet<FileVisitOption> fileVisitOpts;
        if (Arrays.toList(options).contains(java.nio.file.LinkOption.NOFOLLOW_LINKS) {
            fileVisitOpts = EnumSet.noneOf(FileVisitOption.class) 
        } else {
            fileVisitOpts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
        }
        Files.walkFileTree(source[i], fileVisitOpts, Integer.MAX_VALUE, copyVisitor);
    }

    private class CopyVisitor implements FileVisitor<Path>  {
        final Path source;
        final Path target;
        final CopyOptions[] options;

        CopyVisitor(Path source, Path target, CopyOptions options...) {
             this.source = source;  this.target = target;  this.options = options;
        };

        @Override
        FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        // before visiting entries in a directory we copy the directory
        // (okay if directory already exists).
        Path newdir = target.resolve(source.relativize(dir));
        try {
            Files.copy(dir, newdir, options);
        } catch (FileAlreadyExistsException x) {
            // ignore
        } catch (IOException x) {
            System.err.format("Unable to create: %s: %s%n", newdir, x);
            return SKIP_SUBTREE;
        }
        return CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        Path newfile= target.resolve(source.relativize(file));
        try {
            Files.copy(file, newfile, options);
        } catch (IOException x) {
            System.err.format("Unable to copy: %s: %s%n", source, x);
        }
        return CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        // fix up modification time of directory when done
        if (exc == null && Arrays.toList(options).contains(COPY_ATTRIBUTES)) {
            Path newdir = target.resolve(source.relativize(dir));
            try {
                FileTime time = Files.getLastModifiedTime(dir);
                Files.setLastModifiedTime(newdir, time);
            } catch (IOException x) {
                System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
            }
        }
        return CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        if (exc instanceof FileSystemLoopException) {
            System.err.println("cycle detected: " + file);
        } else {
            System.err.format("Unable to copy: %s: %s%n", file, exc);
        }
        return CONTINUE;
    }
}

Копирование каталога или файла

long bytes = java.nio.file.Files.copy( 
                 new java.io.File("<filepath1>").toPath(), 
                 new java.io.File("<filepath2>").toPath(),
                 java.nio.file.StandardCopyOption.REPLACE_EXISTING,
                 java.nio.file.StandardCopyOption.COPY_ATTRIBUTES,
                 java.nio.file.LinkOption.NOFOLLOW_LINKS);

Перемещение каталога или файла

long bytes = java.nio.file.Files.move( 
                 new java.io.File("<filepath1>").toPath(), 
                 new java.io.File("<filepath2>").toPath(),
                 java.nio.file.StandardCopyOption.ATOMIC_MOVE,
                 java.nio.file.StandardCopyOption.REPLACE_EXISTING);

Рекурсивное копирование каталога или файла

long bytes = com.yourcompany.nio.Files.copyRecursive( 
                 new java.io.File("<filepath1>").toPath(), 
                 new java.io.File("<filepath2>").toPath(),
                 java.nio.file.StandardCopyOption.REPLACE_EXISTING,
                 java.nio.file.StandardCopyOption.COPY_ATTRIBUTES
                 java.nio.file.LinkOption.NOFOLLOW_LINKS );

Имя пакета для файлов было неправильным (должно быть java.nio.file, а не java.nio). Я отправил правку для этого; надеюсь, что все в порядке!

Stuart Rossiter 03.12.2014 16:15

Нет смысла писать new java.io.File("<filepath1>").toPath(), если вы вообще можете использовать Paths.get("<filepath1>").

Holger 12.03.2021 10:11

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

public void copy(File src, File dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            // Transfer bytes from in to out
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

Это сработает, но я не думаю, что это лучше, чем другие ответы здесь?

Rup 23.10.2013 18:18

@Rup Это значительно лучше, чем другие ответы здесь, (а) потому что, он работает, и (б) потому, что он не полагается на стороннее программное обеспечение.

user207421 19.07.2014 13:41

@EJP Хорошо, но это не очень умно. Копирование файла должно быть операцией ОС или файловой системы, а не приложением: мы надеемся, что Java сможет обнаружить копию и превратить ее в операцию ОС, за исключением случаев, когда вы явно читаете файл, когда вы останавливаете его выполнение. Если вы не думаете, что Java может это сделать, доверяете ли вы ей в оптимизации чтения и записи размером 1 КБ в более крупные блоки? И если источник и место назначения находились на удаленном общем ресурсе в медленной сети, то это явно делает ненужную работу. Да, некоторые сторонние JAR-файлы слишком большие (Guava!), Но они добавляют много подобного, сделанного правильно.

Rup 19.07.2014 14:02

Работал как шарм. Лучшее решение, не требующее сторонних библиотек и работающее на java 1.6. Спасибо.

James Wierzba 16.04.2015 22:36

@Rup Я согласен с тем, что это должна быть функция операционной системы, но я не могу понять ваш комментарий иначе. В части после первого двоеточия где-то отсутствует глагол; Я бы тоже не стал "доверять" и ожидать, что Java превратит 1k блоков во что-то большее, хотя я бы сам определенно использовал гораздо большие блоки; Я бы никогда не написал приложение, которое в первую очередь использовало бы общие файлы; и я не знаю, что какая-либо сторонняя библиотека делает что-то более «правильное» (что бы вы под этим ни подразумевали), чем этот код, за исключением, вероятно, использования большего буфера.

user207421 17.05.2015 21:01

@EJP Под «правильным» я имел в виду 1) использование лучших доступных API, например. более новые IO, где это возможно 2) представление вызовов Java таким образом, чтобы он мог легко распознать, что это копия файла - например, каналы, представляющие целые файлы для чтения и записи, как и в других ответах здесь, и превращают их в один вызов ОС. Я думаю, что этот подход настолько медленный, насколько это возможно, особенно с небольшим буфером.

Rup 18.05.2015 11:59

Этот код неверен. InputStream.read может вернуть 0, даже если данных больше. InputStream.read возвращает -1, если данных больше нет. Таким образом, цикл должен завершиться, когда он вернет -1, а не 0.

Reinstate Monica 07.09.2018 19:55

Быстро и работает со всеми версиями Java, а также Android:

private void copy(final File f1, final File f2) throws IOException {
    f2.createNewFile();

    final RandomAccessFile file1 = new RandomAccessFile(f1, "r");
    final RandomAccessFile file2 = new RandomAccessFile(f2, "rw");

    file2.getChannel().write(file1.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length()));

    file1.close();
    file2.close();
}

Не все файловые системы поддерживают файлы с отображением памяти, и я думаю, что для небольших файлов это относительно дорого.

Rup 14.11.2013 14:48

Не работает ни с одной версией Java до 1.4, и нет ничего, что могло бы гарантировать, что одной записи будет достаточно.

user207421 19.07.2014 13:44

public static void copyFile(File src, File dst) throws IOException
{
    long p = 0, dp, size;
    FileChannel in = null, out = null;

    try
    {
        if (!dst.exists()) dst.createNewFile();

        in = new FileInputStream(src).getChannel();
        out = new FileOutputStream(dst).getChannel();
        size = in.size();

        while ((dp = out.transferFrom(in, p, size)) > 0)
        {
            p += dp;
        }
    }
    finally {
        try
        {
            if (out != null) out.close();
        }
        finally {
            if (in != null) in.close();
        }
    }
}

Таким образом, отличие от принятого ответа состоит в том, что у вас есть transferFrom в цикле while?

Rup 16.01.2014 15:41

Даже не компилируется, а вызов createNewFile () избыточен и расточителен.

user207421 19.07.2014 13:43

В Java 7 это просто ...

File src = new File("original.txt");
File target = new File("copy.txt");

Files.copy(src.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);

Что ваш ответ добавляет к ответам Скотта или Глена?

Uri Agassi 20.06.2014 23:59

Это кратко, лучше меньше, да лучше. Их ответы хороши и подробны, но я их пропустил при просмотре. К сожалению, на этот вопрос есть много ответов, и многие из них длинные, устаревшие и сложные, и хорошие ответы Скотта и Глена в этом потерялись (я дам положительные голоса, чтобы помочь с этим). Интересно, можно ли улучшить мой ответ, сократив его до трех строк, выбив exists () и сообщение об ошибке.

Kevin Sadler 21.06.2014 12:18

Это не работает для каталогов. Блин, все ошибаются. Больше из-за связи API проблема ваша ошибка. Я тоже ошибся.

mmm 17.01.2015 13:06

@momo вопрос был как скопировать файл.

Kevin Sadler 21.01.2015 15:01

Если вам нужен File, не нужно объезжать Path. Files.copy(Paths.get("original.txt"), Paths.get("copy.txt"), …)

Holger 12.03.2021 10:13

Вот три способа, с помощью которых вы можете легко копировать файлы с помощью одной строки кода!

Java7:

java.nio.file.Files # copy

private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
    Files.copy(source.toPath(), dest.toPath());
}

Appache Commons IO:

FileUtils # copyFile

private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
    FileUtils.copyFile(source, dest);
}

Гуава:

Файлы # копия

private static void copyFileUsingGuava(File source,File dest) throws IOException{
    Files.copy(source,dest);          
}

Первый не работает для каталогов. Блин, все ошибаются. Больше из-за связи API проблема ваша ошибка. Я тоже ошибся.

mmm 17.01.2015 13:07

Сначала нужно 3 параметра. Files.copy, использующий только 2 параметра, предназначен для Path - Stream. Просто добавьте параметр StandardCopyOption.COPY_ATTRIBUTES или StandardCopyOption.REPLACE_EXISTING для Path в Path

Pimp Trizkit 17.02.2016 00:18

Копия NIO с буфером - самая быстрая согласно моему тесту. См. Рабочий код ниже из моего тестового проекта на https://github.com/mhisoft/fastcopy

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;


public class test {

private static final int BUFFER = 4096*16;
static final DecimalFormat df = new DecimalFormat("#,###.##");
public static void nioBufferCopy(final File source, final File target )  {
    FileChannel in = null;
    FileChannel out = null;
    double  size=0;
    long overallT1 =  System.currentTimeMillis();

    try {
        in = new FileInputStream(source).getChannel();
        out = new FileOutputStream(target).getChannel();
        size = in.size();
        double size2InKB = size / 1024 ;
        ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER);

        while (in.read(buffer) != -1) {
            buffer.flip();

            while(buffer.hasRemaining()){
                out.write(buffer);
            }

            buffer.clear();
        }
        long overallT2 =  System.currentTimeMillis();
        System.out.println(String.format("Copied %s KB in %s millisecs", df.format(size2InKB),  (overallT2 - overallT1)));
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    finally {
        close(in);
        close(out);
    }
}

private static void close(Closeable closable)  {
    if (closable != null) {
        try {
            closable.close();
        } catch (IOException e) {
            if (FastCopy.debug)
                e.printStackTrace();
        }    
    }
}

}

отлично! это быстрее, чем стандартный поток java.io .. копирование 10 ГБ всего за 160 секунд

aswzen 13.10.2016 07:44

Немного поздно для вечеринки, но вот сравнение времени, затраченного на копирование файла с использованием различных методов копирования файлов. Я повторил методы 10 раз и взял среднее значение. Передача файлов с использованием потоков ввода-вывода кажется худшим кандидатом:

Comparison of file transfer using various methods

Вот методы:

private static long fileCopyUsingFileStreams(File fileToCopy, File newFile) throws IOException {
    FileInputStream input = new FileInputStream(fileToCopy);
    FileOutputStream output = new FileOutputStream(newFile);
    byte[] buf = new byte[1024];
    int bytesRead;
    long start = System.currentTimeMillis();
    while ((bytesRead = input.read(buf)) > 0)
    {
        output.write(buf, 0, bytesRead);
    }
    long end = System.currentTimeMillis();

    input.close();
    output.close();

    return (end-start);
}

private static long fileCopyUsingNIOChannelClass(File fileToCopy, File newFile) throws IOException
{
    FileInputStream inputStream = new FileInputStream(fileToCopy);
    FileChannel inChannel = inputStream.getChannel();

    FileOutputStream outputStream = new FileOutputStream(newFile);
    FileChannel outChannel = outputStream.getChannel();

    long start = System.currentTimeMillis();
    inChannel.transferTo(0, fileToCopy.length(), outChannel);
    long end = System.currentTimeMillis();

    inputStream.close();
    outputStream.close();

    return (end-start);
}

private static long fileCopyUsingApacheCommons(File fileToCopy, File newFile) throws IOException
{
    long start = System.currentTimeMillis();
    FileUtils.copyFile(fileToCopy, newFile);
    long end = System.currentTimeMillis();
    return (end-start);
}

private static long fileCopyUsingNIOFilesClass(File fileToCopy, File newFile) throws IOException
{
    Path source = Paths.get(fileToCopy.getPath());
    Path destination = Paths.get(newFile.getPath());
    long start = System.currentTimeMillis();
    Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
    long end = System.currentTimeMillis();

    return (end-start);
}

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

Другие вопросы по теме