尽可能以最快的方式复制大文件

AvB*_*AvB 2 java multithreading filechannel file-copying

我试图找到一种以最快的方式复制大文件的方法......

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class FastFileCopy {


public static void main(String[] args) {
    try {
        String from = "...";
        String to = "...";
        FileInputStream fis = new FileInputStream(from);
        FileOutputStream fos = new FileOutputStream(to);
        ArrayList<Transfer> transfers = new ArrayList<>();
        long position = 0, estimate;
        int count = 1024 * 64;
        boolean lastChunk = false;
        while (true) {
            if (position + count < fis.getChannel().size()) {
                transfers.add(new Transfer(fis, fos, position, position + count));
                position += count + 1;
                estimate = position + count;
                if (estimate >= fis.getChannel().size()) {
                    lastChunk = true;
                }
            } else {
                lastChunk = true;
            }
            if (lastChunk) {
                transfers.add(new Transfer(fis, fos, position, fis.getChannel().size()));
                break;
            }
        }
        for (Transfer transfer : transfers) {
            transfer.start();
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

}
Run Code Online (Sandbox Code Playgroud)

然后创建这个类:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class Transfer extends Thread {

private FileChannel inChannel = null;
private FileChannel outChannel = null;
private long position, count;

public Transfer(FileInputStream fis, FileOutputStream fos, long position, long count) {
    this.position = position;
    this.count = count;
    inChannel = fis.getChannel();
    outChannel = fos.getChannel();
}

@Override
public void run() {
    try {
        inChannel.transferTo(position, count, outChannel);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}
Run Code Online (Sandbox Code Playgroud)

我测试了它,结果非常令人印象深刻......但是有一个很大的问题,复制的文件比当前文件大得多!

所以,请检查一下,帮我找到问题,谢谢:))

fge*_*fge 6

这是一个XY问题.只是用Files.copy().

看看那个,看看这对你来说不够快:

$ ls -lh ~/ubuntu-13.04-desktop-amd64.iso 
-rw-rw-r-- 1 fge fge 785M Jul 12  2013 /home/fge/ubuntu-13.04-desktop-amd64.iso
$ cat Foo.java 
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class Foo
{
    public static void main(final String... args)
        throws IOException
    {
        Files.copy(Paths.get("/home/fge/ubuntu-13.04-desktop-amd64.iso"),
            Paths.get("/tmp/t.iso"), StandardCopyOption.REPLACE_EXISTING);
    }
}
$ time java Foo

real    0m1.860s
user    0m0.077s
sys 0m0.648s
$ time java Foo

real    0m1.851s
user    0m0.101s
sys 0m0.598s
Run Code Online (Sandbox Code Playgroud)

它甚至可能更快.天知道为什么,Oracle不使用,sendfile(2)即使这是Java 8和Linux 2.2已经存在了相当长的一段时间.

  • 在任何有自尊的开发人员的机器上,该程序会将文件缓存在内存中,操作系统将在程序结束后*写回脏的 FS 缓存。在程序执行后添加时间同步并添加时间。 (2认同)