Cách ngắn gọn tiêu chuẩn để sao chép một tệp trong Java?


421

Tôi luôn băn khoăn rằng cách duy nhất để sao chép một tệp trong Java là mở các luồng, khai báo một bộ đệm, đọc trong một tệp, lặp qua nó và ghi nó ra hơi nước khác. Các trang web được rải rác với các triển khai tương tự, nhưng vẫn hơi khác nhau của loại giải pháp này.

Có cách nào tốt hơn nằm trong giới hạn của ngôn ngữ Java (nghĩa là không liên quan đến các lệnh cụ thể của hệ điều hành)? Có lẽ trong một số gói tiện ích nguồn mở đáng tin cậy, điều đó ít nhất sẽ che khuất việc triển khai cơ bản này và cung cấp giải pháp một dòng?


5
Có thể có một cái gì đó trong Apache Commons FileUtils , cụ thể là các phương thức copyFile .
bộ công cụ

22
Nếu sử dụng Java 7, thay vào đó, hãy sử dụng Files.copy, như được đề xuất bởi @GlenBest: stackoverflow.com/a/16600787/44737
cướp

Câu trả lời:


274

Như bộ công cụ đã đề cập ở trên, Apache Commons IO là con đường để đi, cụ thể là FileUtils . copyFile () ; nó xử lý tất cả các nâng nặng cho bạn.

Và như một phần tái bút, lưu ý rằng các phiên bản gần đây của FileUtils (như bản phát hành 2.0.1) đã thêm việc sử dụng NIO để sao chép tệp; NIO có thể tăng đáng kể hiệu năng sao chép tệp , phần lớn do NIO thường xuyên trì hoãn sao chép trực tiếp vào hệ điều hành / hệ thống tệp chứ không phải xử lý nó bằng cách đọc và ghi byte qua lớp Java. Vì vậy, nếu bạn đang tìm kiếm hiệu suất, có thể đáng để kiểm tra xem bạn có đang sử dụng phiên bản FileUtils gần đây không.


1
Rất hữu ích - bạn có hiểu biết sâu sắc về việc khi nào một bản phát hành chính thức sẽ kết hợp những thay đổi này không?
Peter

2
Bản phát hành công khai của Apache Commons IO vẫn ở mức 1.4, grrrrrrr
Peter

14
Kể từ tháng 12 năm 2010, Apache Commons IO ở mức 2.0.1, có chức năng NIO. Trả lời cập nhật.
Simon Nickerson

4
Một cảnh báo cho người dùng Android: điều này KHÔNG được bao gồm trong các API Android tiêu chuẩn
IlDan

18
Nếu sử dụng Java 7 hoặc mới hơn, bạn có thể sử dụng Files.copy theo đề xuất của @GlenBest: stackoverflow.com/a/16600787/44737
cướp

278

Tôi sẽ tránh việc sử dụng một api lớn như apache commons. Đây là một hoạt động đơn giản và được tích hợp vào JDK trong gói NIO mới. Nó đã được liên kết với câu trả lời trước đó, nhưng phương thức chính trong api NIO là các hàm mới "transferTo" và "transferFrom".

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

Một trong những bài viết được liên kết cho thấy một cách tuyệt vời về cách tích hợp chức năng này vào mã của bạn, bằng cách sử dụng 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();
        }
    }
}

Học NIO có thể hơi khó, vì vậy bạn có thể muốn tin tưởng vào thợ máy này trước khi ra ngoài và cố gắng học NIO qua đêm. Từ kinh nghiệm cá nhân, có thể là một điều rất khó học nếu bạn không có kinh nghiệm và được giới thiệu về IO thông qua các luồng java.io.


2
Cảm ơn, thông tin hữu ích. Tôi vẫn sẽ tranh luận về một cái gì đó giống như Apache Commons, đặc biệt nếu nó sử dụng nio (đúng cách) bên dưới; nhưng tôi đồng ý điều quan trọng là phải hiểu các nguyên tắc cơ bản cơ bản.
Peter

1
Thật không may, có hãy cẩn thận. Khi tôi sao chép tệp 1,5 Gb trên Windows 7, 32 bit, nó không thể ánh xạ tệp. Tôi đã phải tìm một giải pháp khác.
Anton K.

15
Ba vấn đề có thể xảy ra với đoạn mã trên: (a) nếu getChannel ném ngoại lệ, bạn có thể rò rỉ một luồng mở; (b) đối với các tệp lớn, bạn có thể đang cố gắng chuyển nhiều hơn một lần so với hệ điều hành có thể xử lý; (c) bạn đang bỏ qua giá trị trả về của transferFrom, vì vậy nó có thể đang sao chép chỉ là một phần của tệp. Đây là lý do tại sao org.apache.tools.ant.util.ResourceUtils.copyResource rất phức tạp. Cũng lưu ý rằng trong khi transferFrom vẫn ổn, transferTo break trên JDK 1.4 trên Linux: bug.sun.com/ormsdatabase/view_orms.do?orms_id=5056395
Jesse Glick

7
Tôi tin rằng phiên bản cập nhật này giải quyết những mối quan tâm đó: gist.github.com/889747
Mark Renouf

11
Mã này có một vấn đề lớn . transferTo () phải được gọi trong một vòng lặp. Nó không đảm bảo để chuyển toàn bộ số tiền yêu cầu.
Hầu tước Lorne

180

Bây giờ với Java 7, bạn có thể sử dụng cú pháp try-with-resource sau đây:

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() );
    }
}

Hoặc, tốt hơn nữa, điều này cũng có thể được thực hiện bằng cách sử dụng lớp Tệp mới được giới thiệu trong Java 7:

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

Khá snazzy, eh?


15
Thật tuyệt vời Java đã không thêm những thứ như thế này trước ngày hôm nay. Một số hoạt động chỉ là những yếu tố cần thiết tuyệt đối của việc viết phần mềm máy tính. Các nhà phát triển Java của Java có thể học một hoặc hai điều từ các hệ điều hành, xem xét những dịch vụ họ cung cấp, để làm cho nó dễ dàng hơn cho những người mới di chuyển qua.
Rick Hodgin

2
À cảm ơn! Tôi đã không biết về lớp "Tệp" mới với tất cả các chức năng trợ giúp của nó. Nó có chính xác những gì tôi cần. Cảm ơn ví dụ.
ChrisCantrell

1
hiệu suất khôn ngoan, java NIO FileChannel tốt hơn, hãy đọc bài viết này journaldev.com/861/4-ways-to-copy-file-in-java
Pankaj

5
Mã này có một vấn đề lớn . transferTo () phải được gọi trong một vòng lặp. Nó không đảm bảo để chuyển toàn bộ số tiền yêu cầu.
Hầu tước Lorne

@Scott: Pete đã yêu cầu giải pháp một dòng và bạn rất gần ... không cần thiết phải bọc Files.copy theo phương thức copyFile. Tôi chỉ cần đặt Files.copy (Đường dẫn từ, Đường dẫn đến) vào đầu câu trả lời của bạn và đề cập rằng bạn có thể sử dụng File.toPath () nếu bạn có các đối tượng Tệp hiện có: Files.copy (fromFile.toPath (), toFile.toPath ())
cướp

89
  • Các phương thức này được thiết kế hiệu năng (chúng tích hợp với I / O gốc của hệ điều hành).
  • Các phương pháp này làm việc với các tập tin, thư mục và liên kết.
  • Mỗi tùy chọn được cung cấp có thể bị bỏ qua - chúng là tùy chọn.

Lớp tiện ích

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;
    }
}

Sao chép một thư mục hoặc tập tin

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);

Di chuyển một thư mục hoặc tập tin

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);

Sao chép một thư mục hoặc tập tin đệ quy

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 );

Tên gói cho Tệp đã sai (phải là java.nio.file chứ không phải java.nio). Tôi đã gửi một bản chỉnh sửa cho điều đó; hy vọng điều đó ổn!
Stuart Rossiter

43

Trong Java 7 thật dễ dàng ...

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

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

1
Câu trả lời của bạn thêm gì vào Scott's hay Glen?
Uri Agassi

11
Nó ngắn gọn, ít hơn là nhiều. Câu trả lời của họ rất hay và chi tiết, nhưng tôi đã bỏ lỡ chúng khi xem qua. Thật không may, có rất nhiều câu trả lời cho vấn đề này và rất nhiều trong số chúng dài, lỗi thời và phức tạp và những câu trả lời hay của Scott và Glen đã bị mất trong đó (tôi sẽ từ bỏ để giúp đỡ điều đó). Tôi tự hỏi nếu câu trả lời của tôi có thể được cải thiện bằng cách giảm nó xuống ba dòng bằng cách loại bỏ thông báo lỗi () và thông báo lỗi.
Kevin Sadler

Điều này không làm việc cho các thư mục. Chết tiệt tất cả mọi người đang nhận được điều này sai. Thêm một vấn đề giao tiếp API là lỗi của bạn. Tôi cũng đã hiểu sai.
mmm

2
@momo câu hỏi là làm thế nào để sao chép một tập tin.
Kevin Sadler

28

Để sao chép một tập tin và lưu nó vào đường dẫn đích của bạn, bạn có thể sử dụng phương pháp bên dưới.

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();
    }
}

1
Điều này sẽ làm việc, nhưng tôi không nghĩ rằng nó tốt hơn các câu trả lời khác ở đây?
Rupi

2
@Rup Nó tốt hơn đáng kể so với các câu trả lời khác ở đây, (a) nó hoạt động và (b) vì nó không phụ thuộc vào phần mềm của bên thứ ba.
Hầu tước Lorne

1
@EJP OK, nhưng nó không thông minh lắm. Sao chép tệp phải là một hoạt động của hệ điều hành hoặc hệ thống tệp, không phải là hoạt động của ứng dụng: Java hy vọng có thể phát hiện ra một bản sao và biến nó thành một hoạt động của hệ điều hành ngoại trừ bằng cách đọc rõ ràng tệp khi bạn dừng việc đó. Nếu bạn không nghĩ Java có thể làm điều đó, bạn có tin tưởng nó để tối ưu hóa việc đọc và ghi 1K thành các khối lớn hơn không? Và nếu nguồn và đích nằm trên một chia sẻ từ xa qua mạng chậm thì rõ ràng đây là công việc không cần thiết. Có một số JAR của bên thứ ba rất lớn (Guava!) Nhưng họ đã thêm rất nhiều thứ như thế này được thực hiện đúng cách.
Rup

Làm việc như người ở. Giải pháp tốt nhất không yêu cầu thư viện bên thứ 3 và hoạt động trên java 1.6. Cảm ơn.
James Wierzba

@Rup Tôi đồng ý rằng nó phải là một chức năng của hệ điều hành, nhưng tôi không thể hiểu ý kiến ​​nào khác của bạn. Phần sau dấu hai chấm đầu tiên thiếu một động từ ở đâu đó; Tôi cũng không 'tin tưởng' sẽ không mong đợi Java biến các khối 1k thành một thứ gì đó lớn hơn, mặc dù tôi chắc chắn sẽ tự mình sử dụng các khối lớn hơn nhiều; Tôi sẽ không bao giờ viết một ứng dụng sử dụng các tệp được chia sẻ ở nơi đầu tiên; và tôi không biết rằng bất kỳ thư viện bên thứ ba nào cũng làm bất cứ điều gì 'phù hợp' (bất kể ý của bạn là gì) so với mã này, ngoại trừ có thể sử dụng bộ đệm lớn hơn.
Hầu tước Lorne

24

Lưu ý rằng tất cả các cơ chế này chỉ sao chép nội dung của tệp, không phải siêu dữ liệu như quyền. Vì vậy, nếu bạn đã sao chép hoặc di chuyển tệp .sh thực thi trên linux, tệp mới sẽ không thể thực thi được.

Để thực sự sao chép hoặc di chuyển một tệp, tức là để có được kết quả tương tự như sao chép từ một dòng lệnh, bạn thực sự cần phải sử dụng một công cụ gốc. Hoặc là một kịch bản shell hoặc JNI.

Rõ ràng, điều này có thể được sửa trong java 7 - http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html . Ngón tay đan chéo!


23

Thư viện Guava của Google cũng có phương pháp sao chép :

sao chép khoảng trống tĩnh công khai ( Tệp  từ,
                         Tệp  đến)
                 ném IOException
Sao chép tất cả các byte từ tệp này sang tệp khác.

Cảnh báo: Nếu tođại diện cho một tệp hiện có, tệp đó sẽ bị ghi đè bằng nội dung của from. Nếu tofromtham chiếu đến cùng một tệp, nội dung của tệp đó sẽ bị xóa.

Tham số:from - tệp nguồn to- tệp đích

Ném: IOException - nếu xảy ra lỗi I / O IllegalArgumentException- nếufrom.equals(to)



7

Ba vấn đề có thể xảy ra với đoạn mã trên:

  1. Nếu getChannel ném một ngoại lệ, bạn có thể rò rỉ một luồng mở.
  2. Đối với các tệp lớn, bạn có thể đang cố gắng chuyển nhiều hơn một lần so với hệ điều hành có thể xử lý.
  3. Bạn đang bỏ qua giá trị trả về của transferFrom, vì vậy nó có thể đang sao chép chỉ là một phần của tệp.

Đây là lý do tại sao org.apache.tools.ant.util.ResourceUtils.copyResourcerất phức tạp. Cũng lưu ý rằng trong khi transferFrom vẫn ổn, transferTo break trên JDK 1.4 trên Linux (xem Bug ID: 5056395 ) - Jesse Glick Jan


7

Nếu bạn đang ở trong một ứng dụng web đã sử dụng Spring và nếu bạn không muốn bao gồm Apache Commons IO để sao chép tệp đơn giản, bạn có thể sử dụng FileCopyUtils của khung công tác Spring.


7

Dưới đây là ba cách mà bạn có thể dễ dàng sao chép các tệp với một dòng mã!

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);
}

Quả ổi :

Tệp # sao chép

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

Đầu tiên không làm việc cho các thư mục. Chết tiệt tất cả mọi người đang nhận được điều này sai. Thêm một vấn đề giao tiếp API là lỗi của bạn. Tôi cũng đã hiểu sai.
mmm

Đầu tiên cần 3 tham số. Files.copychỉ sử dụng 2 tham số là Pathđể Stream. Chỉ cần thêm tham số StandardCopyOption.COPY_ATTRIBUTEShoặc StandardCopyOption.REPLACE_EXISTINGcho PathtớiPath
Pimp Trizkit

6
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();
        }
    }
}

Vì vậy, sự khác biệt từ câu trả lời được chấp nhận hàng đầu là bạn đã có transferFrom trong một vòng lặp?
Rupi

1
Thậm chí không biên dịch và lệnh gọi newNewFile () là dư thừa và lãng phí.
Hầu tước Lorne

3

Bản sao NIO với bộ đệm là nhanh nhất theo thử nghiệm của tôi. Xem mã làm việc dưới đây từ một dự án thử nghiệm của tôi tại 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();
        }    
    }
}

}


đẹp! cái này nhanh chứ không phải là dòng java.io độc lập .. sao chép 10GB chỉ trong 160 giây
vào

2

Nhanh chóng và hoạt động với tất cả các phiên bản Java cũng như 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();
}

1
Mặc dù vậy, không phải tất cả các hệ thống tệp đều hỗ trợ các tệp ánh xạ bộ nhớ và tôi nghĩ rằng nó tương đối đắt đối với các tệp nhỏ.
Rupi

Không hoạt động với bất kỳ phiên bản Java nào trước 1.4 và không có gì đảm bảo một lần ghi là đủ.
Hầu tước Lorne

1

Một chút muộn cho bữa tiệc, nhưng đây là so sánh thời gian thực hiện để sao chép một tệp bằng các phương pháp sao chép tệp khác nhau. Tôi đã lặp qua các phương thức trong 10 lần và lấy trung bình. Truyền tệp bằng luồng IO dường như là ứng cử viên tồi tệ nhất:

So sánh chuyển tập tin bằng nhiều phương pháp khác nhau

Dưới đây là các phương pháp:

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);
}

Hạn chế duy nhất mà tôi có thể thấy khi sử dụng lớp kênh NIO là dường như tôi vẫn không thể tìm thấy cách hiển thị tiến trình sao chép tệp trung gian.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.