在Java中复制大量文件的最快方法是什么?到目前为止,我使用过文件流和nio。总体而言,流似乎比nio更快。您有什么经验吗?
在Java中复制大量文件的最快方法是什么?到目前为止,我使用过文件流和nio。总体而言,流似乎比nio更快。您有什么经验吗?
http://www.baptiste-wicht.com/2010/08/file-copy-in-java-benchmark/ 可能会为您提供答案。
对于基准测试,我使用了不同的文件进行测试。
- 小文件(5 KB)
- 中等文件(50 KB)
- 大文件(5 MB)
- 超大文件(50 MB)
- 还有一个巨大的二进制文件(1.3 GB)
我先使用文本文件进行测试,然后使用二进制文件进行测试。我使用三种模式进行测试:
- 在同一硬盘上。这是一个带有8 MB缓存的250 GB IDE硬盘。它采用Ext4格式。
- 在两个磁盘之间传输。我使用了第一个硬盘和另一个带有16 MB缓存的250 GB SATA硬盘。它采用Ext4格式。
- 在两个磁盘之间传输。我使用了第一个硬盘和另一个带有32 MB缓存的1 TB SATA硬盘。它采用NTFS格式。
我使用基准测试框架(在此处描述)对所有方法进行测试。这些测试是在我的个人计算机上进行的(Ubuntu 10.04 64位、Intel Core 2 Duo 3.16 GHz、6 GB DDR2、SATA硬盘)。所使用的Java版本是Java 7 64位虚拟机...
我会使用:
import java.io.*;
import java.nio.channels.*;
public class FileUtils{
public static void copyFile(File in, File out)
throws IOException
{
FileChannel inChannel = new
FileInputStream(in).getChannel();
FileChannel outChannel = new
FileOutputStream(out).getChannel();
try {
inChannel.transferTo(0, inChannel.size(),
outChannel);
}
catch (IOException e) {
throw e;
}
finally {
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
}
}
public static void main(String args[]) throws IOException{
FileUtils.copyFile(new File(args[0]),new File(args[1]));
}
}
如果您在Windows中有任何文件大小超过64M,您可能需要查看这个链接: http://forums.sun.com/thread.jspa?threadID=439695&messageID=2917510
使用流
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
使用通道
private static void copyFileUsingChannel(File source, File dest) throws IOException {
FileChannel sourceChannel = null;
FileChannel destChannel = null;
try {
sourceChannel = new FileInputStream(source).getChannel();
destChannel = new FileOutputStream(dest).getChannel();
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}finally{
sourceChannel.close();
destChannel.close();
}
}
使用Apache Commons IO库
private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
性能测试
File source = new File("/Users/tmp/source.avi");
File dest = new File("/Users/tmp/dest.avi");
//copy file conventional way using Stream
long start = System.nanoTime();
copyFileUsingStream(source, dest);
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
//copy files using java.nio FileChannel
source = new File("/Users/tmp/sourceChannel.avi");
dest = new File("/Users/tmp/destChannel.avi");
start = System.nanoTime();
copyFileUsingChannel(source, dest);
System.out.println("Time taken by Channel Copy = "+(System.nanoTime()-start));
//copy files using apache commons io
source = new File("/Users/tmp/sourceApache.avi");
dest = new File("/Users/tmp/destApache.avi");
start = System.nanoTime();
copyFileUsingApacheCommonsIO(source, dest);
System.out.println("Time taken by Apache Commons IO Copy = "+(System.nanoTime()-start));
//using Java 7 Files class
source = new File("/Users/tmp/sourceJava7.avi");
dest = new File("/Users/tmp/destJava7.avi");
start = System.nanoTime();
copyFileUsingJava7Files(source, dest);
System.out.println("Time taken by Java7 Files Copy = "+(System.nanoTime()-start));
结果
Time taken by Stream Copy = 44,582,575,000
Time taken by Java7 Files Copy = 89,061,578,000
Time taken by Channel Copy = 104,138,195,000
Time taken by Apache Commons IO Copy = 108,396,714,000
这取决于文件(更大的文件),对我来说,使用缓冲流是最快的方式。
public void copyFile(File inFileStr, File outFileStr) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inFileStr));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFileStr))) {
byte[] buffer = new byte[1024 * 1024];
int read = 0;
while ((read = bis.read(buffer)) != -1) {
bos.write(buffer, 0, read);
}
bis.close();
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
FileUtils.copyFile(new File(sourcePath), new File(destPath));
使用 FileChannel 进行IO操作。
或者使用 java.nio.file.Files
的 copy()
方法。
让Java分叉一个操作系统批处理脚本来复制文件。你的代码可能需要编写批处理脚本。