1. 程式人生 > >java復制文件的4種方式

java復制文件的4種方式

date family gpo exceptio 處理 nio use 效率 read

一、使用FileStreams復制

這是最經典的方式將一個文件的內容復制到另一個文件中。 使用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的數據,所以這應該是一個低效率的,下一個方法我們將看到新的方式。

二、使用FileChannel復制

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 }

三、使用Commons IO復制

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復制

四、使用Java7的Files類復制

如果你有一些經驗在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中四種不同的方法可以復制一個文件。

java復制文件的4種方式