这是最经典的方式将一个文件的内容复制到另一个文件中。 使用FileInputStream读取文件A的字节,使用FileOutputStream写入到文件B。 这是第一个方法的代码:
1 private static void copyFileUsingFileStreams(File source, File dest) 2 throws IOException { 3 InputStream input = null; 4 OutputStream output = null; 5 try { 6 input = new FileInputStream(source); 7 output = new FileOutputStream(dest); 8 byte[] buf = new byte[1024]; 9 int bytesRead; 10 while ((bytesRead = input.read(buf)) != -1) { 11 output.write(buf, 0, bytesRead); 12 } 13 } finally { 14 input.close(); 15 output.close(); 16 } 17 }
正如你所看到的我们执行几个读和写操作try的数据,所以这应该是一个低效率的,下一个方法我们将看到新的方式。
Java NIO包括transferFrom方法,根据文档应该比文件流复制的速度更快。 这是第二种方法的代码:
1 private static void copyFileUsingFileChannels(File source, File dest) throws IOException { 2 FileChannel inputChannel = null; 3 FileChannel outputChannel = null; 4 try { 5 inputChannel = new FileInputStream(source).getChannel(); 6 outputChannel = new FileOutputStream(dest).getChannel(); 7 outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); 8 } finally { 9 inputChannel.close(); 10 outputChannel.close(); 11 } 12 }
Apache Commons IO提供拷贝文件方法在其FileUtils类,可用于复制一个文件到另一个地方。它非常方便使用Apache Commons FileUtils类时,您已经使用您的项目。基本上,这个类使用Java NIO FileChannel内部。 这是第三种方法的代码:
1 private static void copyFileUsingApacheCommonsIO(File source, File dest) 2 throws IOException { 3 FileUtils.copyFile(source, dest); 4 }
该方法的核心代码如下:
1 private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { 2 if (destFile.exists() && destFile.isDirectory()) { 3 throw new IOException("Destination '" + destFile + "' exists but is a directory"); 4 } 5 6 FileInputStream fis = null; 7 FileOutputStream fos = null; 8 FileChannel input = null; 9 FileChannel output = null; 10 try { 11 fis = new FileInputStream(srcFile); 12 fos = new FileOutputStream(destFile); 13 input = fis.getChannel(); 14 output = fos.getChannel(); 15 long size = input.size(); 16 long pos = 0; 17 long count = 0; 18 while (pos < size) { 19 count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos; 20 pos += output.transferFrom(input, pos, count); 21 } 22 } finally { 23 IOUtils.closeQuietly(output); 24 IOUtils.closeQuietly(fos); 25 IOUtils.closeQuietly(input); 26 IOUtils.closeQuietly(fis); 27 } 28 29 if (srcFile.length() != destFile.length()) { 30 throw new IOException("Failed to copy full contents from '" + 31 srcFile + "' to '" + destFile + "'"); 32 } 33 if (preserveFileDate) { 34 destFile.setLastModified(srcFile.lastModified()); 35 } 36 }
由此可见,使用Apache Commons IO复制文件的原理就是上述第二种方法:使用FileChannel复制
如果你有一些经验在Java 7中你可能会知道,可以使用复制方法的Files类文件,从一个文件复制到另一个文件。 这是第四个方法的代码:
1 private static void copyFileUsingJava7Files(File source, File dest) 2 throws IOException { 3 Files.copy(source.toPath(), dest.toPath()); 4 }
现在看到这些方法中的哪一个是更高效的,我们会复制一个大文件使用每一个在一个简单的程序。 从缓存来避免任何性能明显我们将使用四个不同的源文件和四种不同的目标文件。 让我们看一下代码:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.nio.channels.FileChannel; 8 import java.nio.file.Files; 9 import org.apache.commons.io.FileUtils; 10 11 public class CopyFilesExample { 12 13 public static void main(String[] args) throws InterruptedException, 14 IOException { 15 16 File source = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile1.txt"); 17 File dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile1.txt"); 18 19 // copy file using FileStreamslong start = System.nanoTime(); 20 long end; 21 copyFileUsingFileStreams(source, dest); 22 System.out.println("Time taken by FileStreams Copy = " 23 + (System.nanoTime() - start)); 24 25 // copy files using java.nio.FileChannelsource = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile2.txt"); 26 dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile2.txt"); 27 start = System.nanoTime(); 28 copyFileUsingFileChannels(source, dest); 29 end = System.nanoTime(); 30 System.out.println("Time taken by FileChannels Copy = " + (end - start)); 31 32 // copy file using Java 7 Files classsource = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile3.txt"); 33 dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile3.txt"); 34 start = System.nanoTime(); 35 copyFileUsingJava7Files(source, dest); 36 end = System.nanoTime(); 37 System.out.println("Time taken by Java7 Files Copy = " + (end - start)); 38 39 // copy files using apache commons iosource = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile4.txt"); 40 dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile4.txt"); 41 start = System.nanoTime(); 42 copyFileUsingApacheCommonsIO(source, dest); 43 end = System.nanoTime(); 44 System.out.println("Time taken by Apache Commons IO Copy = " 45 + (end - start)); 46 47 } 48 49 private static void copyFileUsingFileStreams(File source, File dest) 50 throws IOException { 51 InputStream input = null; 52 OutputStream output = null; 53 try { 54 input = new FileInputStream(source); 55 output = new FileOutputStream(dest); 56 byte[] buf = new byte[1024]; 57 int bytesRead; 58 while ((bytesRead = input.read(buf)) > 0) { 59 output.write(buf, 0, bytesRead); 60 } 61 } finally { 62 input.close(); 63 output.close(); 64 } 65 } 66 67 private static void copyFileUsingFileChannels(File source, File dest) 68 throws IOException { 69 FileChannel inputChannel = null; 70 FileChannel outputChannel = null; 71 try { 72 inputChannel = new FileInputStream(source).getChannel(); 73 outputChannel = new FileOutputStream(dest).getChannel(); 74 outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); 75 } finally { 76 inputChannel.close(); 77 outputChannel.close(); 78 } 79 } 80 81 private static void copyFileUsingJava7Files(File source, File dest) 82 throws IOException { 83 Files.copy(source.toPath(), dest.toPath()); 84 } 85 86 private static void copyFileUsingApacheCommonsIO(File source, File dest) 87 throws IOException { 88 FileUtils.copyFile(source, dest); 89 } 90 91 }
输出:
Time taken by FileStreams Copy = 127572360 Time taken by FileChannels Copy = 10449963 Time taken by Java7 Files Copy = 10808333 Time taken by Apache Commons IO Copy = 17971677
正如您可以看到的FileChannels拷贝大文件是最好的方法。如果你处理更大的文件,你会注意到一个更大的速度差。 这是一个示例,该示例演示了Java中四种不同的方法可以复制一个文件。