使用FileInputStream+BufferedInputStream与FileOutputStream+BufferedOutputStream实现文件复制,是很多人普遍想到的一种方法。在这里,我将给出另外一种方法,使用FileChannel通道。其实,还有一些其他方法,想了解更多,清参见我转载的文章:JAVA NIO 简介。
不多说,直接贴出源码:
srcFile和destFile:均为文件而非目录;
overlay:指示是否覆盖已存在目标文件。
package com.pluto.file; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; public class FileCopy { private final int BUFFER_SIZE = 4096; public long bufferCopyFile(File srcFile, File destFile, boolean overlay) throws FileNotFoundException { if (!srcFile.exists()) { throw new FileNotFoundException("At path " + srcFile.getAbsolutePath()); } if (destFile.exists() && overlay) { destFile.delete(); } BufferedInputStream bufin = new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bufout = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] buffer = new byte[BUFFER_SIZE]; long totalBytesReaded = 0; int bytesReaded = -1; try { while ((bytesReaded = bufin.read(buffer, 0, BUFFER_SIZE)) != -1) { bufout.write(buffer, 0, bytesReaded); totalBytesReaded += bytesReaded; } } catch (IOException e) { e.printStackTrace(); } finally { try { bufin.close(); bufout.close(); } catch (IOException e) { e.printStackTrace(); } } return totalBytesReaded; } public long channelCopyFile(File srcFile, File destFile, boolean overlay) throws FileNotFoundException { if (!srcFile.exists()) { throw new FileNotFoundException("At path " + srcFile.getAbsolutePath()); } if (destFile.exists() && overlay) { destFile.delete(); } // 获取源文件和目标文件的输入输出流 FileInputStream fin = new FileInputStream(srcFile); FileOutputStream fout = new FileOutputStream(destFile); // 获取输入输出通道 FileChannel fcin = fin.getChannel(); FileChannel fcout = fout.getChannel(); long totalBytesReaded = 0; try{ totalBytesReaded = fcin.transferTo(0, fcin.size(), fcout); }catch(IOException e){ e.printStackTrace(); } finally { try { fin.close(); fout.close(); fcin.close(); fcout.close(); } catch (IOException e) { e.printStackTrace(); } } return totalBytesReaded; } }
在本机上面做了个简单的性能测试。在下面的测试源码中,beautiful.rmvb是一个600M左右的文件
FileCopy fileCopy = new FileCopy(); File srcFile = new File("/home/pluto/temporary/filecopy/beautiful.rmvb"); File destFile1 = new File("/home/pluto/temporary/filecopy/dest/b.rmvb"); File destFile2 = new File("/home/pluto/temporary/filecopy/dest/be.rmvb"); long totalBytes = 0; long start = System.currentTimeMillis(); try { totalBytes = fileCopy.bufferCopyFile(srcFile, destFile1, false); } catch (FileNotFoundException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("bufferCopyFile: " + totalBytes + " spend: " + (end - start)); start = System.currentTimeMillis(); try { totalBytes = fileCopy.channelCopyFile(srcFile, destFile2, false); } catch (FileNotFoundException e) { e.printStackTrace(); } end = System.currentTimeMillis(); System.out.println("\nchannelCopyFile: " + totalBytes + " spend: " + (end - start));
运行输出结果如下:
bufferCopyFile: 685049654 spend: 26077 channelCopyFile: 685049654 spend: 28345
我的电脑性能一般,上面的结果只具有参考性。