基于FileChannel复制文件。
普通的NIO复制
@Test
public void testCopyFile() throws IOException {
nioCopyFile("D:\\spark-2.2.3-bin-hadoop2.7.tgz", "D:\\spark-2.2.3-bin-hadoop2.7.tgz.copy");
}
/**
* @author jimo
*/
private void nioCopyFile(String srcPath, String destPath) throws IOException {
final File srcFile = new File(srcPath);
final File destFile = new File(destPath);
if (!destFile.exists()) {
destFile.createNewFile();
}
int buffSize = 16384;
System.out.println("开始复制, buffer size=" + buffSize);
long start = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
int length;
final ByteBuffer buff = ByteBuffer.allocate(buffSize);
while ((length = inChannel.read(buff)) != -1) {
// System.out.println("读取的字节数:" + length);
// 翻转模式,读完该写了
buff.flip();
int outLen;
while ((outLen = outChannel.write(buff)) != 0) {
// System.out.println("写入的字节数:" + outLen);
}
// 清空buff
buff.clear();
}
// 强制刷新到磁盘
outChannel.force(true);
}
final long end = System.currentTimeMillis();
System.out.println(String.format("文件大小:%d MB,共花费:%d ms", srcFile.length() / 1024 / 1024, (end - start)));
}
测试:
开始复制, buffer size=1024
文件大小:194 MB,共花费:3153 ms
开始复制, buffer size=8192
文件大小:194 MB,共花费:2225 ms
开始复制, buffer size=16384
文件大小:194 MB,共花费:2149 ms
理论上更快的方法
/**
* @author jimo
*/
private void copyFileFast(String srcPath, String destPath) throws IOException {
final File srcFile = new File(srcPath);
final File destFile = new File(destPath);
if (!destFile.exists()) {
destFile.createNewFile();
}
int buffSize = 1024;
System.out.println("开始复制, buffer size=" + buffSize);
long start = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
long size = inChannel.size();
long pos = 0;
// 最大传输的字节数
long cnt;
while (pos < size) {
// 每次复制buffSize的数据
cnt = size - pos > buffSize ? buffSize : size - pos;
pos += outChannel.transferFrom(inChannel, pos, cnt);
}
// 强制刷新到磁盘
outChannel.force(true);
}
final long end = System.currentTimeMillis();
System.out.println(String.format("文件大小:%d MB,共花费:%d ms", srcFile.length() / 1024 / 1024, (end - start)));
}
测试:实际上更差
开始复制, buffer size=16384
文件大小:194 MB,共花费:2400 ms
开始复制, buffer size=8192
文件大小:194 MB,共花费:2993 ms
开始复制, buffer size=1024
文件大小:194 MB,共花费:7475 ms